20개 이상의 항목 목록을 배열로 읽어온 다음 목록에서 4개 항목의 모든 조합을 생성하는 Bash 스크립트

20개 이상의 항목 목록을 배열로 읽어온 다음 목록에서 4개 항목의 모든 조합을 생성하는 Bash 스크립트

38개 단어(한 줄에 하나씩) 목록이 포함된 "ingredients.txt" 파일이 있습니다. 배열로 읽는 방법을 알아냈습니다.

getArray() {
    array=() 
    while IFS= read -r line 
    do
        array+=("$line")
    done < "$1"
}

getArray "ingredients.txt"

하지만 이제 38개 목록에서 정확히 4개 단어의 모든 조합을 출력하는 방법은 무엇입니까?

편집: 의견에 대한 응답으로 순열이 아닌 조합을 의미했으며 중복은 효과가 없습니다. 각 조합에는 4개의 고유한 단어가 있습니다.

좀 더 명확하게 설명하자면, 이것을 가방에서 38가지 색상의 구슬 4개를 뽑는다고 생각해보세요. 두 가지 색상이 동일하지 않습니다. 빨간색 조합을 한 번 그리면 해당 조합에 대해 다른 빨간색 조합을 그릴 수 없습니다. 4개를 칠하고 색상을 기록한 다음 다시 가방에 넣고 4개를 더 칠합니다. {파란색, 노란색, 보라색, 빨간색}과 {노란색, 보라색, 빨간색, 파란색}을 얻으면 별도로 계산되지 않습니다. 나는 단지 순열이 아닌 조합을 원합니다.

또한 양파, 치즈, 고기, 상추, 당근, 셀러리, 무당근, 상추, 셀러리, 식초 등 각 조합(성분 목록으로 돌아가기)을 인쇄하고 싶습니다.

이것이 분명하기를 바랍니다.

답변1

파이썬에서는:

import itertools.combinations

with open('ingredients.txt') as fd:
    words= fd.readlines()
    for combination in itertools.combinations(words, 4):
        print(combination)

답변2

파이썬을 사용해보려고 해요

>>> a
['praveen', 'ajay', 'abhi', 'chetan', 'abh', 'cat']


for i in range(0,len(a),4):
...     print a[i:i+4]
...
['praveen', 'ajay', 'abhi', 'chetan']
['abh', 'cat']

답변3

재미를 위해 일반 bash로 작성된 버전입니다(긴 목록과 함께 사용하는 것을 권장하지 않습니다. 매우 느립니다(예상대로). c에서 수행된 작업을 0.5초 안에 수행하는 데 셸에서 2분 이상이 걸립니다.) :

#!/bin/bash -
set -u

readarray -t b <ingredients.txt

r=${1:-3}
n=${2:-5}

main(){
          combinations
      }


combinations(){  : ${r:=3}    ${n:=5}    # default values

        ## The first line of elements is easy, fill an array of r elements:
        for ((i=0 ; i<r ; i++)); do 
            a[i]=$i
        done
        printelements

        ## Up to the maximum permitted value of the first array element.
        while (( a[0] < n-r )); do
            ## search backwards on the array for a value less than maximum.
            for ((i = r-1; i >= 0; i--)); do
            ## If an item is below its maximum permitted value...
            if ((a[i] < n-r+i )); then 
                ## increment it:
                ((a[i]++))
                break
            fi
            done
            ## Fill the rest of the array with consecutive values:
            for (( i = i + 1 ; i < r ; i++ )); do
            (( a[i] = a[i-1] + 1 ))
            done
            ## Print the current combination of items:
            printelements
        done
         }

printelements(){ : #p=${a[@]/%/ }; printf '%s\n' "<${p% }>"; }
                 s=""
                 for i in "${a[@]}"; do
                     printf '%s' "$s" "${b[i]}"
                     s=" "
                 done
                 echo
               }

main

다음과 같이 실행하세요:

$ ./script 4 38

다음을 인쇄합니다:

$ ./script 4 38 | wc -l
73815

수학적으로 확인되는 것처럼(사실은 라이브러리 정의 함수입니다):

$ bc <<<"r=4;n=38;fact(n)/(fact(r)*fact(n-r))"    # n! / ( r! × (n-r)! )
73815

답변4

그럼 아래 코드를 사용해 보세요

getArray() {
    array=() 
    while IFS= read -r line 
    do
        array+=("$line")
    done < "$1"
    for i in ${!array[@]}
    do
           if [ ${#array[$i]} == 4 ]; then
                    echo "${array[$i]}"
           fi
    done
}

getArray "ingredients.txt"

관련 정보