나는 ID 조합이 다른 순서로 반복되는 것을 원하지 않기 때문에 이것이 진정한 순열이라고 믿지 않습니다.
1부터 x까지의 ID가 포함된 목록이 있습니다.
List #1: 1001 1002 1003 1004
List #2: 1002 1004 1005
List #3: 1001 1003 1006
List #4: 1002 1003 1005 1006 1007 1008 1010
등.
목록의 길이는 가변적이라는 점을 염두에 두고 목록에서 가능한 모든 ID 조합을 얻을 수 있는 방법이 필요합니다(그러나 다른 순서의 동일한 조합은 아님).
예를 들어 목록 #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
목록 #2는 다음을 반환합니다.
1002
1004
1005
1002 1004
1002 1005
1004 1005
1002 1004 1005
Bash 스크립트에서 작동하는 솔루션이 필요합니다. 공평하게 말하면 Python, PHP 등을 호출할 수 있습니다.
어떤 의견이라도 높이 평가하겠습니다.
답변1
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
그리고 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
답변3
IVlad를 기반으로 하는 또 다른 Bash 솔루션바이너리 반복 방법, 또한 빌린교정기 확장 아이디어사이러스(Cyrus)와 말테 스코루파(Malte Skoruppa)로부터일반화하다:
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
집합의 요소 수입니다. 또한 함수가 호출될 때마다 이진 배열을 구축하므로 시간이 절약되지 않습니다. 변수 네임스페이스를 오염시키지 않도록 모두 하위 쉘에 싸여 있습니다. 이 질문의 예제 출력에 따르면 "null" 또는 빈 세트는 구체적으로 제외됩니다.