1

I am searching for a simple command/function to generate permutation of a numbers set given as a parameters of a shell command.

Here on example I can generate all 6-number permutations from 1-6 numbers in Python:

root@debian:~# python
Python 2.7.13 (default, Sep 26 2018, 18:42:22)
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from itertools import permutations
>>> perm = permutations([1, 2, 3, 4, 5, 6], 6)
>>> for i in list(perm):
...     print i
...
(1, 2, 3, 4, 5, 6)
(1, 2, 3, 4, 6, 5)
(1, 2, 3, 5, 4, 6)
(1, 2, 3, 5, 6, 4)
(1, 2, 3, 6, 4, 5)
(1, 2, 3, 6, 5, 4)
(1, 2, 4, 3, 5, 6)
[...]

How do do it in a simpler way, best with an one-liner command where all such numbers as an arguments can be provided, for example:

$ command 1 2 3 4 5 6

with output expected as:

1 2 3 4 5 6
1 2 3 4 6 5
1 2 3 5 4 6
1 2 3 5 6 4
1 2 3 6 4 5
1 2 3 6 5 4
1 2 4 3 5 6
[...]

Update: Only one line is printed out with when script uses arguments:

root@debian:~# cat permut.py
import sys
n1 = sys.argv[1]
n2 = sys.argv[2]
n3 = sys.argv[3]
n4 = sys.argv[4]
n5 = sys.argv[5]
n6 = sys.argv[6]
from itertools import combinations
comb = combinations([sys.argv[1], n2, n3, n4, n5, n6], 6)
for i in list(comb):
        print i
root@debian:~# python permut.py 1 2 3 4 5 6
('1', '2', '3', '4', '5', '6')
root@debian:~#

While when numbers are provided in the scipt it works good, why?

root@debian:~# cat permut2.py
from itertools import permutations
perm = permutations([21, 2, 30, 34, 15, 46], 6)
for i in list(perm):
        print i
root@debian:~# python permut2.py|head -10
(21, 2, 30, 34, 15, 46)
(21, 2, 30, 34, 46, 15)
(21, 2, 30, 15, 34, 46)
(21, 2, 30, 15, 46, 34)
(21, 2, 30, 46, 34, 15)
(21, 2, 30, 46, 15, 34)
(21, 2, 34, 30, 15, 46)
(21, 2, 34, 30, 46, 15)
(21, 2, 34, 15, 30, 46)
(21, 2, 34, 15, 46, 30)

Also with "int(sys.argv)" does not work:

root@debian:~# cat permut.py
import sys
n1 = int(sys.argv[1])
n2 = int(sys.argv[2])
n3 = int(sys.argv[3])
n4 = int(sys.argv[4])
n5 = int(sys.argv[5])
n6 = int(sys.argv[6])
from itertools import combinations
comb = combinations([n1, n2, n3, n4, n5, n6], 6)
for i in list(comb):
        print i
root@debian:~# python permut.py 1 2 3 4 5 6
(1, 2, 3, 4, 5, 6)
root@debian:~#
Chris
  • 939
  • 2
  • 11
  • 22
  • 3
    You can also turn your Python commands into a Python script, and use that as `command`. – 9769953 Mar 28 '20 at 11:31
  • I am voting to reopen as the question I myself selected does not actually give an answer to this, which asks for a one-liner. I have written such a simple one-liner that I'd like to share here. – Enlico Mar 28 '20 at 12:01
  • I showed python code as the only option I found for my case, I am not a python programmer and was expecting something simpler, even using a bash. The proposed url does not answer my question at all (completely different case and input). – Chris Mar 28 '20 at 12:10
  • I have the onliner, however: `echo {1..6}{1..6}{1..6}{1..6}{1..6}{1..6} | sed -E 's/[^ ]*([0-9])[0-9]*\1[^ ]*( |$)//g'`. If they reopen the question, I'll post it as an answer. – Enlico Mar 28 '20 at 12:44
  • The onliner in previous command does not support other cases, any set of 6 numbers, for example permutation without repetition of 12, 4, 43, 30, 65, 23 – Chris Mar 28 '20 at 12:58
  • It supports only one digit-numbers. `sed` has not builtin arithmetic capabilities, so there's no one-line way to make it work with any numbers. – Enlico Mar 28 '20 at 13:17
  • Any hint to the update I added to the ticker? Why python with args does not work well? – Chris Mar 28 '20 at 13:20
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/210492/discussion-between-enrico-maria-de-angelis-and-chris). – Enlico Mar 28 '20 at 15:16

2 Answers2

1

Take the list of command line parameters and for each permutation of this list display individual values separated with spaces.

import itertools
import sys

for p in itertools.permutations(sys.argv[1:]):
    print(" ".join(p))
dlask
  • 8,776
  • 1
  • 26
  • 30
0

Update

The following oneliner does what the OP asks.

echo {12,4,43,30}","{12,4,43,30}","{12,4,43,30}","{12,4,43,30} | sed -E 's/\<([0-9]+,)*([0-9]+),([0-9]+,)*\2(,[0-9]+)*\>( |$)//g;s/ +/\n/g'

It works like this:

  • the echo command generates the nⁿ space-separated permutations separating the numbers of each permutation by commas;
    • (clearly any way of generating this is fine, as the tricky part is discarding the permutations which have repetitions.)
  • the sed command
    1. makes the magic with one substitution
    2. puts each permutation on a line with the second substitution s/ +/\n/g.

Original answer

The following oneliner works for the original answer, which used only single digit-numbers:

echo {1..6}{1..6}{1..6}{1..6}{1..6}{1..6} | sed -E 's/[^ ]*([0-9])[0-9]*\1[^ ]*( |$)//g'

I don't doubt it might be successfully adapted to work with multiple digit numbers, but at the moment I have no idea.

Enlico
  • 23,259
  • 6
  • 48
  • 102