Одним из способов решения этой проблемы было бы добавить следующее в .bashrc
:
if [ -f /usr/bin/fish ]; then
exec /usr/bin/fish
fi
Обратная сторона: как пользователю рыбы, вам иногда нужно POSIX-совместимая оболочка. Если вы выполните bash
, взломанный выше метод даст вам вместо этого еще одну рыбную раковину.
Использование 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
$ 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
Еще одно решение 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
- количество элементов в наборе. Это также неэффективно по времени, так как каждый из этих двоичных массивов раз вы вызываете функцию. Это все завернутый во вспомогательную оболочку, поэтому он не загрязняет пространство имен переменных. Он специально исключает "нулевой" или пустой набор, согласно образцу выходных данных этого Вопроса.
С 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