1

I have a file "ingredients.txt" that has a list of 38 words (one per each line). I have figured out how to read it into an array

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

But now how to get output of all combinations of exactly 4 words from the list of 38?

EDIT: To respond to a comment, I do mean combinations and not permutations, and repetitions are not valid. Four unique words in each combination.

To further clarify, think of it as drawing four marbles of 38 different colors from a bag. No two colors alike. Once you draw a red one, it is impossible to draw another red one for that combination. You draw four, write down the colors, and put them back in the bag, and draw another four. If you get {blue, yellow, purple, red} and {yellow, purple, red, blue} they are not counted separately. I just want combinations, not permutations.

Also, I want each combination printed (going back to the ingredients list): onion, cheese, meat, bun lettuce, carrot, celery, radish carrot, lettuce, celery, vinegar etc.

I hope this is clear.

4
  • 5
    This strikes me as something you'd probably want to write in a some other programming language, not bash.
    – Kusalananda
    CommentedOct 12, 2018 at 5:46
  • Please read: Combinations and Permutations And say: Is repetition valid? e.g: (a,a,a,a). Is order important? That is: are (a,b,c,d) and (d,b,a,c) equivalent?
    – user232326
    CommentedOct 12, 2018 at 8:09
  • You can also use the bash mapfile command to get the file into an array: mapfile -t array < ingredients.txtCommentedOct 12, 2018 at 14:55
  • I meant what I said, combinations, not permutations. And no, repetition is not valid. Needs to be four unique words.
    – gracious1
    CommentedOct 16, 2018 at 23:37

4 Answers 4

1

In Python:

import itertools.combinations with open('ingredients.txt') as fd: words= fd.readlines() for combination in itertools.combinations(words, 4): print(combination) 
2
  • This can be inserted into a bash script as is? (Not experienced with python.)
    – gracious1
    CommentedOct 17, 2018 at 4:31
  • I see that you can't, what is the best syntax for inserting this into bash script?
    – gracious1
    CommentedOct 17, 2018 at 4:37
0

I tried by using python

>>> 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'] 
    0

    Just for the fun of it, a version in plain bash (which I do not recommend using for long lists, it is quite slow (as should be expected), it takes more than two minutes to do in shell what in c gets done in half a second.):

    #!/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 

    Running it as:

    $ ./script 4 38 

    Will print:

    $ ./script 4 38 | wc -l 73815 

    As math will confirm (fact is a library defined function):

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

      Well, try with below code

      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" 
      1
      • There's readarray in bash, and the code does not give any combinations of four words, only the words that are four characters long. This you could have done through a fairly simple grep command or similar, or awk 'length == 4'.
        – Kusalananda
        CommentedOct 12, 2018 at 6:54

      You must log in to answer this question.

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.