Python itertools permutations running very slow

144 views Asked by At

Running in SuSE linux,

This is a quick and dirty script to solve a geocaching puzzle (GC9K63A).
First attempt to do anything in python. I added the print "." to give proof of life, but dot doesn't appear. Previously left running for a week with out a result.

   items = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ,14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
    from itertools import permutations
    for perm in permutations(items):
    
     A=perm[0]
     B=perm[1]
     C=perm[2]
     D=perm[3]
     E=perm[4]
     F=perm[5]
     G=perm[6]
     H=perm[7]
     I=perm[8]
     J=perm[9]
     K=perm[10]
     L=perm[11]
     M=perm[12]
     N=perm[13]
     O=perm[14]
     P=perm[15]
     Q=perm[16]
     R=perm[17]
     S=perm[18]
     T=perm[19]
     U=perm[20]
     V=perm[21]
     W=perm[22]
     X=perm[23]
     Y=perm[24]
     Z=perm[25]
    
    
     if     (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) == -55 and (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) == -37 and (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) == -27 and (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) == 13 and (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) == -59 and (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) == 7 and (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) == 91 and (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) == 19 and (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) == -51 and (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) == 79 and (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) == 29 and (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) == -5 and (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) == -5 and (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) == 55 and (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) == 1 and (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) == -57 and (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) == -117 and (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) == 51 and (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) == 3 
    
    
    
         print  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
    
    else:
         print "."


1

There are 1 answers

2
Jonas V On BEST ANSWER

There are a few details to point out here.

First off, you said you let this code run for a week without a result.
Notice that, even if a result is found, it would not stop. So if you haven't looked through the entire output, there is a good chance there actually was a result, but it got washed away by the dots following after it.
Adding such a condition would be as easy as including a break statement after you printed your result.

Next, in the statements right after your for loop begins, you step for step assign new values to the different variables named by letters. This can be done via unpacking within the forloop. This should lead to a slight speedup, but also just makes the code easier to read.

Lastly, the io operation of printing may actually slow your code down significantly.
To be sure of this, I tried this out:
I added a counter at the beginning, and added to the print statement this counter.
That way I could see how many permutations the script could handle within a given time frame.
Running it about 10 seconds leads to about 100000 permutations being checked.
Then I added an additional if clause, that checks if the counter is divisible by 100000, and only then prints the line.
In the same 10 seconds, this version of the script checks 2500000 permutations.

The modified code I arrived at at the very end looks like this:

counter = 0
items = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ,14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
from itertools import permutations
for 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 in permutations(items):
  if (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) == -55 and (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) == -37 and (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) == -27 and (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) == 13 and (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) == -59 and (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) == 7 and (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) == 91 and (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) == 19 and (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) == -51 and (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) == 79 and (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) == 29 and (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) == -5 and (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) == -5 and (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) == 55 and (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) == 1 and (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) == -57 and (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) == -117 and (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) == 51 and (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) == 3 :
    print (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)
    break
  else:
    counter += 1
    if counter % 100000 == 0:
      print (".", counter)

It's also worthwile to keep in mind that the amount of permutations to check here is just pretty gigantic, so even with these optimizations, it will likely still take quite a while.
To be precise, the amount of permutations to check here is !25 = 15511210043330985984000000, which even if you would be able to increase the check rate by a million fold, would still take about two million years.
Unless you have a few livetimes to wait, you are probably better off looking for a analytical solution