#trifid crib placer #subroutines def get_cipher(): file = raw_input("Cipher name: ") fid = open(file) ciphertext = fid.read() fid.close() return ciphertext def convert_string(text): chars = "ABCDEFGHIJKLM" chars += "NOPQRSTUVWXYZ[" text = text.upper() text = text.replace('#','[') list = [ord(c)-ord('A') for c in text if c in chars] return list def get_labels(cipher,crib,pos,per): label = [None]*3 for row in range(3): label[row] = [-1]*27 # insert -1's before and after crib cbuf = [-1]*pos + crib cbuf += [-1]*(len(cipher)-len(cbuf)) bindex = cindex = count = 0 pstart = bpos = cpos = 0 nxt_label = 0 numb = per # length of first group while pstart < len(cipher): while count < 3*numb: b = cipher[bpos] # cipher letter c = cbuf[cpos] # crib entry if c <> -1: # c is real letter lb = label[bindex][b] lc = label[cindex][c] if lb is -1 and lc is -1: label[bindex][b] = nxt_label label[cindex][c] = nxt_label nxt_label += 1 elif lc is -1: label[cindex][c] = lb elif lb is -1: label[bindex][b] = lc else: # merge labels for i in range(3): for j in range(27): if label[i][j] is lc: label[i][j] = lb count += 1 cpos += 1 # next line % is 'MOD' if (count % numb) is 0: cindex += 1 # next row cpos = pstart # return to start bindex = (bindex+1) % 3 if bindex is 0: bpos += 1 pstart += per cpos = pstart bpos = pstart count = bindex = cindex = 0 if pstart + per > len(cipher): numb = len(cipher) - pstart #Are these labels possible? for i in range(nxt_label): for row in range(3): if label[row].count(i) > 9: return 0 # form two-row combinations c01 = zip(label[0],label[1]) c02 = zip(label[0],label[2]) c12 = zip(label[1],label[2]) for i in range(nxt_label): for j in range(nxt_label): if c01.count( (i,j) ) > 3: return 0 if c02.count( (i,j) ) > 3: return 0 if c12.count( (i,j) ) > 3: return 0 # Check for duplicate columns for i in range(26): c0 = label[0][i] c1 = label[1][i] c2 = label[2][i] if c0 is -1 or c1 is -1 or c2 is -1: continue for j in range(i+1,27): if c0 == label[0][j] and \ c1 == label[1][j] and \ c2 == label[2][j]: return 0 return 1 # passed all tests #main program print "Trifid crib placer" text = get_cipher() print "Cipher is:" print text cipher = convert_string(text) crib = raw_input("Enter crib: ") crib = convert_string(crib) for per in range(5,11): print "Period ",per," OK at", limit = len(cipher)-len(crib)+1 for pos in range(limit): if get_labels(cipher,crib,pos,per): print pos+1, print