How to make permutation in bash with N! input?

后端 未结 3 1114
你的背包
你的背包 2021-01-15 14:44

I have to make a permutation in bash with \"eval\" and \"seq\" commands. So I have to make first a permutation that could contain the same numbers, then I have to filter it

相关标签:
3条回答
  • 2021-01-15 15:29

    I understand this isn't the seq+eval solution the OP wants but in case anyone in future is looking for an alternative, here's an implementation of the generate() function described in the Wikipedia article on Heap's Algorithm written in awk to solve this problem:

    $ cat tst.awk
    function generate(n,A,  i) {
        if (n == 1) {
            output(A)
        }
        else {
            for (i=0; i<(n-1); i++) {
                generate(n-1, A)
                swap(A, (n%2?0:i), n-1)
            }
            generate(n-1, A)
        }
    }
    
    BEGIN{
        if (n>0) {
            for (i=1; i<=n; i++) {
                A[i-1] = i
            }
            generate(n, A)
        }
    }
    
    function output(a, i,g) {g=length(a); for (i=0;i<g;i++) printf "%s%s",a[i],(i<(g-1)?"":ORS)}
    function swap(a,x,y, t) {t=a[x]; a[x]=a[y]; a[y]=t }
    
    $ awk -v n=3 -f tst.awk | sort
    123
    132
    213
    231
    312
    321
    

    I stuck to the Wikipedia article naming and other conventions as much as possible, including starting the array at zero instead of the typical awk 1, for ease of comparison between that article and the awk code.

    0 讨论(0)
  • 2021-01-15 15:33

    If someones curious, heres the solution:

    input=3
    for i in $(eval echo " {1..$input}{1..$input}{1..$input} "); do
        OK=yes
        for pos1 in $(seq 0 $((x,1)) ); do
            for pos2 in $(seq 0 $((x,1)) ); do
                if [ $pos1 != $pos2 ]; then
                    if [ ${i:$pos1:1} == ${i:$pos2:1} ]; then
                        OK=no
                    fi
                fi
            done
        done
        if [ $OK = yes ]; then
            echo $i
        fi
    
    done
    
    0 讨论(0)
  • 2021-01-15 15:46

    It is a permutation problem, so I have found some others have did it. You can see the answer Generating permutations using bash

    So through the answer, you can write the code like this:

    perm() {
        local items="$1"
        local out="$2"
        local i
        [[ "$items" == "" ]] && echo "$out" && return
        for (( i=0; i<${#items}; i++ )) ; do
            perm "${items:0:i}${items:i+1}" "$out${items:i:1}"
        done
    }
    
    test() {
        local number="$1"
        local iniitem="$(seq -s' ' 1 ${number} | sed -n 's/ //g;p')"
        perm "$iniitem"
    }
    

    Then you can use the function like this:
    test 3:
    the output:

    123
    132
    213
    231
    312
    321
    
    0 讨论(0)
提交回复
热议问题