2

I have a project and I am trying to do a complex cryptographic method. Is it normal to use nested loops a lot? Or did I miss something?

I intend to create a method which tries all strings to find password. For example, when I input ['A','B'] it should create each of these one by one:

['A', 'B', 'AA', 'AB', 'BA', 'BB', 'AAA', 'AAB', 'ABA', 'ABB', 'BAA', 'BAB', 'BBA', 'BBB', (triple permutations), (quadruple permutations), and it goes on ...]

My code:

def rulefinder():
global externalrul1
global externalrul2
rul2 = uniquestring1[0]
rul1 = uniquestring1[0]
for n in range (0,3):
 for m in range (0, len(uniquestring1)):
  for z in range(0, n+1):
    for k in range (0,3):
        for i in range(0, len(uniquestring1)):
            for o in range(0, k+1):
                for y in range (0,  len(uniquestring1)):
                    rul2 = rul2[:-1] + uniquestring1[y]
                    for x in range (0, len(uniquestring1)):
                        rul1= rul1[:-1] + uniquestring1[x]
                        code=""
                        for cha in Genx1:
                            if cha==uniquestring1[0]:
                                code +=codereplacer(rul1)
                            elif cha==uniquestring1[1]:
                                code +=codereplacer(rul2)
                        print(code)
                        print(uniquestring1[0],rul1)
                        print(uniquestring1[1],rul2)
                        print(LastString)
                        if code == LastString:
                            axiom1=uniquestring1[0]
                            axiom2=uniquestring1[1]
                            externalrul1=rul1
                            externalrul2=rul2
                            print('rules are found')
                            print("First RULE:", uniquestring1[0], rul1)
                            print("Second RULE:", uniquestring1[1], rul2)
                            findsubgeneration(code, axiom1, rul1, axiom2, rul2)
                            return
                rul1 = rul1[:o] + uniquestring1[i] + rul1[(o + 1):]
        rul1 += codereplacer(uniquestring1[i])
    rul2 = rul2[:z] + uniquestring1[m] + rul2[(z + 1):]
    rul1 =""
 rul2 += codereplacer(uniquestring1[m])
FatihAkici
  • 4,679
  • 2
  • 31
  • 48
vrd.gn
  • 198
  • 1
  • 18
  • 3
    It is a sign of code smell to nest a lot of for loops, look into the `itertools` module. – Francisco Dec 28 '17 at 06:00
  • As @FranciscoCouzo hinted, you might find this other thread interesting: https://stackoverflow.com/q/104420/289011 – Savir Dec 28 '17 at 06:02
  • I have checked them but they do not include some features. For example, 'AA', 'BB', 'CC' cannot be created by 'permutation' method. – vrd.gn Dec 28 '17 at 06:08
  • @VuralErdogan are you intending to join these permutations into strings at the end? Like so: ['A', 'B', 'AA', 'AB', 'BA', 'BB', 'AAA', 'AAB', 'ABA', 'ABB', 'BAA', 'BAB', 'BBA', 'BBB',...] or do you want to keep them as tuples like you described in the question? – FatihAkici Dec 28 '17 at 06:43
  • @FatihAkici ['A', 'B', 'AA', 'AB', 'BA', 'BB', 'AAA', 'AAB', 'ABA', 'ABB', 'BAA', 'BAB', 'BBA', 'BBB'] is exactly what I expect when I enter 'A', 'B'. I just tried to use my own method; however, it is not efficient way. Also, it shows some errors when I increase number of characters. – vrd.gn Dec 28 '17 at 07:04

1 Answers1

1

You are doing things in a very MATLAB-ic way (lots of loops, and iterating only on the index, instead of elements of iterables). Pythonic way is much more efficient (uses generators under the hood), and is much cleaner:

import itertools
l = ['A','B']
n = 5 # The size of your "expanding permutations"
res = []
for i in range(1,n):
    res.extend(map(''.join, list(itertools.product(l, repeat=i))))
print res

Result:

['A', 'B', 'AA', 'AB', 'BA', 'BB', 'AAA', 'AAB', 'ABA', 'ABB', 'BAA', 'BAB', 'BBA', 'BBB',
'AAAA', 'AAAB', 'AABA', 'AABB', 'ABAA', 'ABAB', 'ABBA', 'ABBB', 'BAAA', 'BAAB', 'BABA', 'BABB', 'BBAA', 'BBAB', 'BBBA', 'BBBB']

Caution: As long as you are working with a small list, you should be fine but as l grows, the result is going to grow exponentially, and may eat out your memory. Hence, instead of doing an extend to the res list, you can write the results inside the loop into disk, on the fly.

FatihAkici
  • 4,679
  • 2
  • 31
  • 48