# Trifid Relationships by ANCHISES # to accompany Trifid article in Jan-Feb 2008 Computer Column # # Updated by SHMOO to Python3 plus changes to make it agree better with published article. # Article featured ND2003 E-21. MA2021 E-17 also available for processing. # alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ#..." # Dots are errors if seen #.....paste ciphertext and crib here.... T="PP#TNPAUF" #ciphertext must begin at start of a period. ND2003 E-21 C="aininitss" #crib must be lowercase. ND2003 E-21 #if crib begins part way through period, it must be # preceded by dots. So if crib 'hello' starts in fifth # letter of period 9, C="....hello" #T="NSSOPUECKEARK" # MA21 E-17 #C="argestinthewo" # MA21 E-17 len_cipher=len(T) len_crib=len(C) #...... Period defined here .... period=9 # insert period here. ND2003 E-21. #period=7 # MA 21 E-17 # TransEqualityValue takes the numeric value and turn it into the equality # type in the article. 0 becomes A1, or the first coordinate of A, # 75 becomes P3 or the third coordinate of P. SHMOO addition def TransEqualityValue(val) : #return str(val) global alphabet # 27 "letter" alphabet valD= val // 30 # used 30 not 27 to increment fractionated row values. valR= val % 30 # Again, ANCHISES used 30 not 27 for this. return alphabet[valR]+str(valD+1) def make_arrays(T,C,len_cipher,len_crib): #.....remove spaces...... t=-1 for j in range (len_crib): if C[j] != ' ': t+=1 pt[t] = C[j] t=-1 for j in range (len_cipher): if T[j] != ' ': t+=1 ct[t] = T[j] if (T[j]=='#'): ct[t]='[' len_cipher=t+1 return(pt,ct,len_cipher) def make_ribbons(pt,ct,len_cipher): nob=len_cipher//period # was len_cipher/period #.......make rib_p[]........ print("period=",period,"len_cipher=",len_cipher,"nob=",nob) #...full periods.... t=-1 for j in range(nob): for m in range(0,3,1): for k in range(period): t=t+1 if(pt[(j*period)+k]=='.'): rib_p[t]=-1; else: x=ord(pt[(j*period)+k])-97+(30*m) # there's the value 30 rib_p[t]=x #.... part period at end... tail=len_cipher-(nob*period) for m in range(3): for j in range(tail): x=ord(pt[(nob*period)+j])-97+(30*m) # there's the value 30 t=t+1; rib_p[t]=x len_r=t+1 #.....make rib_c[]................... #...full periods.... t=-1 for j in range(nob): for k in range(period): for m in range(3): t=t+1 x=ord(ct[j*period+k])-65+(30*m) # 30 seen rib_c[t]=x #...part period at end..... tail=len_cipher-(nob*period) for j in range(tail): for m in range (3): x=ord(ct[nob*period+j]) - 65 +(30*m) # 30 seen t=t+1; rib_c[t]=x return(rib_p,rib_c,len_r) #.......START............ pt=['.']*500; ct=[0]*1000 rib_p=[0]*500; rib_c=[0]*500 line=[None]*20 #make array line[20][50] index=['A']*27 for x in range(20): line[x]=[None]*50 len_line=[0]*30 grid=[None]*3 for row in range(3): grid[row]=[None]*27 #grid[3][27] len_r=0 pt,ct,len_cipher=make_arrays(T,C,len_cipher,len_crib) #make plain & cipher arrays, pt[] & ct[] rib_p,rib_c,len_r=make_ribbons(pt,ct,len_cipher) #make plain and cipher ribbons, rib_p[] & rib_c[] print( "pt[]: ",end="") for j in range (len_cipher): print( pt[j],end="") print() print ("ct[]: ",end="" ) for j in range (len_cipher): val=ct[j] # SHMOO adjustment. Originally ct[i] but prints [ if(ct[j]=='[') : val= '#' # replace [ with # print( val,end="") print() print("Plain ribbon from crib:") for j in range(3*len_cipher): print(TransEqualityValue(rib_p[j]),' ',end="") print() print("Cipher ribbon from ciphertext:" ) for j in range(3*len_cipher): print(TransEqualityValue(rib_c[j]),' ',end="") print();print() print("length of ribbon= ",len_r) print() #...make lines..... nol=-1; for m in range(30): len_line[m]=0; for pos in range(len_r): if(rib_c[pos]==-1 or rib_p[pos]==-1): continue #skip if no letter in ribbon nol+=1 # start a new line line[nol][0]=rib_p[pos] # enter 1st plain-cipher pair line[nol][1]=rib_c[pos] len_line[nol]=2 rib_p[pos]=-1; rib_c[pos]=-1 present=1 while present>0: # add all other pairs to row where one matches present=0 for p in range (pos+1,len_r): #..search rest of ribbon for match if(rib_c[p]==-1 or rib_p[p]==-1): continue #skip if ribbon empty flag=0 for k in range(len_line[nol]): if(rib_p[p]==line[nol][k]): flag=1 # match found to crib part break for k in range(len_line[nol]): if(rib_c[p]==line[nol][k]): flag+=10 # match found to cipher part break if(flag==1): # where match found, add part to line line[nol][len_line[nol]]=rib_c[p] len_line[nol]+=1 present=1 if(flag==10): line[nol][len_line[nol]]=rib_p[p] len_line[nol]+=1 present=1 if(flag>0): rib_p[p]=-1; rib_c[p]=-1 # delete parts from ribbons nol+=1 print("number of lines = ", nol," (a,b,c... arbitrary, see JF2008 p12,13 text)") for p in range(nol): print( chr(97+p)," ",end="") for q in range(len_line[p]): print (TransEqualityValue(line[p][q]),' ',end="") print() for row in range(3): #initialise grid[][] for col in range(27): grid[row][col]=-1 for row in range(nol): #put discovered parts into grid for col in range(len_line[row]): x=line[row][col] while(x>29): x=x%30 y=line[row][col]//30 # was / grid[y][x]=row #find out how many letters have all 3 parts t=-1 for col in range(27): flag=0 for m in range(3): if(grid[m][col]>-1): flag+=1 if(flag==3): t+=1 index[t]=col len_index=t+1 print() print("Here are relationships from the placed crib:") for m in range(len_index): print(alphabet[index[m]],' ',end="") print() for row in range(3): for col in range(len_index): print(chr(97+grid[row][index[col]]),' ',end="") print() print()