Chris
Chris

Reputation: 1019

Permutation without repetition

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:~#

Upvotes: 1

Views: 213

Answers (2)

Enlico
Enlico

Reputation: 28406

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.

Upvotes: 0

dlask
dlask

Reputation: 8982

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))

Upvotes: 1

Related Questions