Перестановки в Bash (комбинации IDs/Tokens)

Одним из способов решения этой проблемы было бы добавить следующее в .bashrc :

if [ -f /usr/bin/fish ]; then
    exec /usr/bin/fish
fi

Обратная сторона: как пользователю рыбы, вам иногда нужно POSIX-совместимая оболочка. Если вы выполните bash , взломанный выше метод даст вам вместо этого еще одну рыбную раковину.

3
15.09.2016, 02:40
3 ответа

Использование python:

>>> from itertools import combinations
>>> a = (1001, 1002, 1003, 1004)
>>> [list(combinations(a, i)) for i in range(1, len(a)+1)]
[[(1001,), (1002,), (1003,), (1004,)], [(1001, 1002), (1001, 1003), (1001, 1004), (1002, 1003), (1002, 1004), (1003, 1004)], [(1001, 1002, 1003), (1001, 1002, 1004), (1001, 1003, 1004), (1002, 1003, 1004)], [(1001, 1002, 1003, 1004)]]

Чтобы отобразить это в более удобном формате:

>>> print '\n'.join('\n'.join(' '.join(str(i) for i in c) for c in combinations(a, i)) for i in range(1, len(a)+1))
1001
1002
1003
1004
1001 1002
1001 1003
1001 1004
1002 1003
1002 1004
1003 1004
1001 1002 1003
1001 1002 1004
1001 1003 1004
1002 1003 1004
1001 1002 1003 1004

Запуск из командной строки bash

$ python -c "from itertools import combinations; a=(1001, 1002, 1003, 1004); print '\n'.join('\n'.join(' '.join(str(i) for i in c) for c in combinations(a, i)) for i in range(1, len(a)+1))"
1001
1002
1003
1004
1001 1002
1001 1003
1001 1004
1002 1003
1002 1004
1003 1004
1001 1002 1003
1001 1002 1004
1001 1003 1004
1002 1003 1004
1001 1002 1003 1004

Запуск в качестве функции оболочки

Давайте определим функцию оболочки:

$ combo() { python -c "import sys, itertools; a=sys.argv[1:]; print '\n'.join('\n'.join(' '.join(str(i) for i in c) for c in itertools.combinations(a, i)) for i in range(1, len(a)+1))" "$@"; }

Мы можем запустить работают следующим образом:

$ combo 1001 1002 1003 1004
1001
1002
1003
1004
1001 1002
1001 1003
1001 1004
1002 1003
1002 1004
1003 1004
1001 1002 1003
1001 1002 1004
1001 1003 1004
1002 1003 1004
1001 1002 1003 1004
2
27.01.2020, 21:26

Еще одно решение Bash, основанное на методе двоичной итерации IVlad , также заимствуя идею расширения скобок у Сайруса с обобщением Малте Скоруппы :

function binpowerset() (
  list=($@)
  eval binary=( $(for((i=0; i < ${#list[@]}; i++)); do printf '%s' "{0..1}"; done) )
  nonempty=0
  for((power=0; power < ${#binary[*]}; power++))
  do
    binrep=${binary[power]}
    for ((charindex=0; charindex < ${#list[*]}; charindex++))
    do
      if [[ ${binrep:charindex:1} = "1" ]]
      then
         printf "%s " ${list[charindex]}
         nonempty=1
      fi
    done
    [[ $nonempty -eq 1 ]] && printf "\n"
  done
)

Назовите это так:

$ binpowerset 1001 1003 1006
1006
1003
1003 1006
1001
1001 1006
1001 1003
1001 1003 1006

Это совсем не эффективно с точки зрения пространства, так как создает массив двоичного представления, состоящий из 2 N элементов, где N - количество элементов в наборе. Это также неэффективно по времени, так как каждый из этих двоичных массивов раз вы вызываете функцию. Это все завернутый во вспомогательную оболочку, поэтому он не загрязняет пространство имен переменных. Он специально исключает "нулевой" или пустой набор, согласно образцу выходных данных этого Вопроса.

0
27.01.2020, 21:26

С bash :

#! /bin/bash
declare -a list=(1001 1002 1003 1004)

show() {
    local -a results=()
    let idx=$2
    for (( j = 0; j < $1; j++ )); do
        if (( idx % 2 )); then results=("${results[@]}" "${list[$j]}"); fi
        let idx\>\>=1
    done
    echo "${results[@]}"
}

let n=${#list[@]}
for (( i = 1; i < 2**n; i++ )); do
    show $n $i
done

Возможно, не самая быстрая реализация, но она работает:

1001
1002
1001 1002
1003
1001 1003
1002 1003
1001 1002 1003
1004
1001 1004
1002 1004
1001 1002 1004
1003 1004
1001 1003 1004
1002 1003 1004
1001 1002 1003 1004
0
27.01.2020, 21:26

Теги

Похожие вопросы