Search code examples
pythonpython-3.xlistcode-generationpython-itertools

Why Python does not generate all possible combinations of letters given?


Generate the file's using code

code will return two file with possible combinations!

final file is that to use!

using itertools generating possible combinations of letters

joining tuple to string

maping output to string

writing the output to a file

Reading the generated file and removing uncessary spaces

finally Testing

File : test.py

    #using itertools generating possible combinations of letters given below and writing it to a file

    from itertools import combinations

    a = "lida"
    letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',]

    def Combinations(iterable, size):
        result = combinations(iterable, size)
        #joining tuple to string
        def join_tuple_string(strings_tuple) -> str:
            return ' '.join(strings_tuple)
        #maping output to string
        output = map(join_tuple_string, result)

        end = list(output)
        #writing the output to a file 
        with open('file.txt', 'w') as e:
            e.write(str(end))

    Combinations(letters, 4)
    #Reading the generated file and removing uncessary spaces

    with open('file.txt', 'r') as e:
        a = e.read()

        for i in range(len(a)):
            list = a[i]
            b = list.replace(' ', '')
            with open('final.txt', 'a') as f:
                f.write(b)
# finally Testing
with open('final.txt', 'r') as r:
    file = r.read()

    if 'adil' in file:
        print('present')

    if 'lida' in file:
        print('present')

    else:
        print('not present')

Solution

  • Assuming your question is "Why is 'lida' not found in the file data while 'adil' is?" the answer is: Because you used the wrong itertools function for your task (and/or misunderstood what it does).

    combinations produces all unique subsequences, in order by position in the input iterable. Since your input iterable is in sorted order, your output's elements will always be in sorted order too; 'abcd' will exist, but 'abdc' won't, because d comes after c in the input (no ordering of a, b, c and d except 'abcd' will exist). If you want to include all the various permutations (so 'adil' and 'lida' both appear in the output), you'd want itertools.permutations, not itertools.combinations. Similarly, if you need a letter to be able to repeat (so 'aaaa' is a possible output), you'd want combinations_with_replacement if only unique outputs desired as per combinations, or product (with a repeat argument passed by keyword) if you want all orderings as per permutations.

    Be warned though, the number of outputs gets much larger for permutations; I'd strongly recommend not trying to store them all in memory. Just loop over the permutations object and write them one by one, e.g.:

    with open('file.txt', 'w') as e:
       perms = map(''.join, permutations(iterable, size))   # map(''.join, ...) is an efficient way to change an iterable of tuples of str to single strs
       file.write(f'[{next(perms)!r}')  # Write open bracket and pull initial value
       # Iterate over remaining values
       for perm in perms:
           file.write(f',{perm!r}')  # Write comma and new value
       file.write(']')  # Write close bracket
    

    which still produces a legal list literal in the file, and avoids adding any of those spaces you're trying to avoid in the first place, all without blowing your RAM trying to hold all the permutations at once.