###################################################################### ## CRYPTOGRAM.txt Save this file as CRYPTOGRAM.txt to use it, # # stay in the # ## same directory, get into Maple (by typing: maple ) # ## and then type: read CRYPTOGRAM.txt # ## Then follow the instructions given there # ## # ## Written by Doron Zeilberger, Rutgers University , # ## DoronZeil at gmail dot com # ###################################################################### print(`First Written: 2020: tested for Maple 20 `): print(`Version April 26, 2024 `): print(): print(`This is CRYPTOGRAM.txt, A Maple package to solve and create Cryptogram puzzles`): print(`where one of the 26! permutations of the alphabet is applied to an English sentence`): print(`and one has to decipher it. `): print(`accompanying Shalosh B. Ekhad puzzle book: `): print(`"100 Cryptogram puzzles" `): print(): print(`The most current version is available on WWW at:`): print(` http://sites.math.rutgers.edu/~zeilberg/tokhniot/CRYPTOGRAM.txt .`): print(`Please report all bugs to: DoronZeil at gmail dot com .`): print(): print(`For general help, and a list of the MAIN functions,`): print(` type "ezra();". For specific help type "ezra(procedure_name);" `): print(`For a list of the supporting functions type: ezra1();`): print(): read `ENGLISH.txt`: with(ListTools): with(combinat): ezra1:=proc() if args=NULL then print(`The supporting procedures are: ALPH, ALPHS,ALPHsent, APPLY1, CHILDREN, COMPWS, EXTEND, EXTENDS, ISGOODCODE, ISPROMISING, ISPROMISING1 `): print(` JOIN, NEIS `): else ezra(args): fi: end: ezra:=proc() if args=NULL then print(` CRYPTORGRAM.txt: A Maple package for solving and creating Crypogram Puzzles `): print(`The MAIN procedures are: ANAGRAMS, ANAG2, BT, EXAMPLES, EXS1, EXS3, MakeCR, ME, OVERLAP, RevPuz, SOLVEC, SULAM, SuperW `): print(``): elif nargs=1 and args[1]=ALPH then print(`ALPH(): The alphabet in the usual order. Try:`): print(`ALPH();`): elif nargs=1 and args[1]=ALPHS then print(`ALPHS(): The alphabet according to frequenty. Try:`): print(`ALPHS();`): elif nargs=1 and args[1]=ALPHsent then print(`ALPHsent(C): inputs a sentence C and outputs the sequence of letters in descending frequency.`): print(`Try:`): print(`ALPHsent(C1);`): elif nargs=1 and args[1]=APPLY1 then print(`APPLY1(CODE,WORD,X): Given a set CODE of pairs [coded letter, real letter] and a WORD`): print(`replaces the coded letters by the real letter and otherwise by X. Try:`): print(`APPLY1({[x,a],[y,b]},[x,z,y,y,z],X);`): elif nargs=1 and args[1]=ANAGRAMS then print(`ANAGRAMS(DS,k): all sets of anagrams of k letters, with the database DS. Try:`): print(`ANAGRAMS(ENG(),3);`): elif nargs=1 and args[1]=ANAG2 then print(`ANAG2(DS,W): Finds all the pairs [W1,W2] such that W1 and W2 in the database DS are words and [W1,W2] is an anagram of W. For the Feb. 8, 2023 New York Times Brain tickler try:`): print(`ANAG2(ENG(),[i,r,i,s,h,l,a,c,e]);`): elif nargs=1 and args[1]=BT then print(`BT(DS,N1,LL): Solves a Brain Tickler problem. For the Jan. 6, 2023 try:`): print(`BT(ENG(),6,[{[1,e],[2,x]},{[1,s],[6,y]},{[5,a],[6,l]}]);`): elif nargs=1 and args[1]=CHILDREN then print(`CHILDREN(DS,CR,CODE): Given a cryptogram C and a current partial code, find all the possible extenions`): print(`if none exits, it returns FAIL. Try:`): print(`CHILDREN(ENG(),EXS2()[2][2],{});`): elif nargs=1 and args[1]=COMPWS then print(`COMPWS(DS,WORD,X): Given a data set DS, and a partial tentative word where the unknowns are`): print(`given by X, outputs the set word in the data-base such that it fits the description`): print(`Try: `): print(`COMPWS(ENG(),[l,X,v,X],X);`): elif nargs=1 and args[1]=EXS1 then print(`EXS1(): A list of cryptograms from the New York Times`): elif nargs=1 and args[1]=EXS2 then print(`EXS2(): A list of pairs [SOURCE,CODED]`): elif nargs=1 and args[1]=EXSs then print(`EXS1(): A list of oiriginal sayings`): elif nargs=1 and args[1]=EXTEND then print(`EXTEND(CODE,CWORD,RWORD): Given a coded word WORD and a partial CODE, and a real word RWORD compatible`): print(`with it, find the implied extension. Try:`): print(`EXTEND({},[a,b,c,d],[l,o,v,e]);`): elif nargs=1 and args[1]=EXTENDS then print(`EXTENDS(DS,CWORD): Given a data set DS, and code word CWORD finds the set of all legal extensions`): print(`Try:`): print(`EXTENDS(ENG(),[a,b,c,d]);`): elif nargs=1 and args[1]=GR then print(`GR(DS,N1,L): inputs a list of words DS, a positive integer N1 and a set of {[place,letter]} finds the`): print(`list of all matching words. Try:`): print(`GR(ENG(),5, {[3,e],[5,t]});`): elif nargs=1 and args[1]=ISGOODCODE then print(`ISGOODCODE(CODE): IS CODE a good code? Try:`): print(`ISGOODCODE({[a,b],[c,d]});`): elif nargs=1 and args[1]=ISPROMISING then print(`ISPROMISING(DS,CODE,CR): Given a data-set, DS, a CODE and a cryptogram`): print(`decides whether it is promising. Try`): print(`ISPROMISING(ENG(),[[X,a,a,a]],X);`): elif nargs=1 and args[1]=ISPROMISING1 then print(`ISPROMISING1(DS,W,X): Given a data-set DS, and partiallly filled words with X, decides whether is has exensions`): elif nargs=1 and args[1]=JOIN then print(`JOIN(S1,S2) two sets of Codes S1 and S2 finds their joining. Try:`): print(`CR:=EXS1()[7]; JOIN(EXTENDS(ENG(),CR[1]),EXTENDS(ENG(),CR[2]) ):`): elif nargs=1 and args[1]=MakeCR then print(`MakeCR(P): inputs a saying, and outputs a random cryptogram whose solution it is. Try:`): print(`MakeCR(P1):`): elif nargs=1 and args[1]=ME then print(`ME(DB,i,j): all the catenations of DB[i] and DB[j]. Try:`): print(`nops(ME(ENG(),2,2));`): elif nargs=1 and args[1]=NEIS then print(`NEIS(DB,W): all the neighbors of the word W in the database DB. Try:`): print(`NEIS(ENG(),[s,m,a,r,t]);`): elif nargs=1 and args[1]=OVERLAP then print(`OVERLAP(DS,W1,W2,A): Given two words W1 , W2, and a data-set DS, as well as a positive integer A, finds all V such that W1V and VW2 are words. Try:`): print(`OVERLAP(ENG(),[f,l,e],[e,l,f],2);`): elif nargs=1 and args[1]=RevPuz then print(`RevPuz(DB,K,L): All the pairs of words [w1,w2] such that w1 has K letters that contains the letter L, and w2 is the reverse of the word that`): print(`is obtained by deleting L. For the Septl 20, 2023, Brain Tickler Puzzle of the New York Times. Try:`): print(`RevPuz(ENG(),5,l);`): elif nargs=1 and args[1]=SOLVEC then print(`SOLVEC(DS,CR): inputs a cruptogram puzzle C, in the data-set DS, and finds a solution. Try:`): print(`SOLVEC(ENG(),EXS2()[1][2]);`): print(`Note that sometimes not all the words are in the data base ENG(). For example`): print(` P:=EXS1()[28]: SOLVEC(ENG(),P); returns FAIL, but, try:`): print(`P:=EXS1()[28]; SOLVEC(ENG(),[op(1..5,P),op(7..13,P),P[15]]);`): elif nargs=1 and args[1]=SULAM then print(`SULAM(DB,W,K): all the ladders of size K that start with W. Try:`): print(`SULAM(ENG(),[s,m,a,r,t],5);`): elif nargs=1 and args[1]=SuperW then print(`SuperW(DB,W): all the words containing w, try:`): print(` SuperW(ENG(),[a,p,r]);`): else print(`There is no such thing as`, args): fi: end: CATS:=proc(S) local A: {seq(cat(op(S[A])),A=1..nops(S))}: end: #ANAGRAMS(DS,k): all sets of anagrams of k letters, with the database DS. Try: #ANAGRAMS(ENG(),3); ANAGRAMS:=proc(DS,k) local LU,GU,A,HOPE,T,MA: LU:=DS[k]: GU:={}: for A from 1 to nops(LU) do HOPE:=convert(permute(LU[A]),set) intersect convert(LU,set): if nops(HOPE)>1 then GU:=GU union {HOPE}: fi: od: MA:=max(seq(nops(GU[A]),A=1..nops(GU)) ): for A from 2 to MA do T[A]:={}: od: for A from 1 to nops(GU) do T[nops(GU[A])]:=T[nops(GU[A])] union {GU[A]}: od: [seq(T[A],A=2..MA)]: end: #M1:=[[m,a,i,n,e], [i,s], [t,h,e], [o,n,l,y],[o,n,e],[s,y,l,l,a,b,l,e],[s,t,a,t,e], [t,h,a,t], [b,o,r,d,e,r,s], [o,n,e], [o,t,h,e,r],[s,t,a,t,e]]: C1:=[[v,j,h,x,t],[h,m],[q,x,t],[y,x,e,g],[y,x,t],[m,g,e,e,j,n,e,t],[m,q,j,q,t],[j,x,a],[q,k,t],[y,x,e,g],[m,q,j,q,t],[q,k,j,q], [n,y,z,a,t,z,m],[t,r,j,o,q,e,g],[y,x,t],[y,q,k,t,z],[m,q,j,q,t]]: #EXAMPLES(): A list of pairs [SOURCE,CODED] EXAMPLES:=proc() [ [ [[b,o,y],[i],[w,i,s,h],[i,d],[b,e,e,n],[a],[f,l,y],[o,n],[t,h,e],[w,a,l,l],[y,e,s,t,e,r,d,a,y],[b,e,i,n,g],[a,b,l,e],[t,o],[f,l,y], [w,o,u,l,d],[b,e], [i,n,c,r,e,d,i,b,l,e]] , [[x,q,w],[u],[b,u,r,p],[u,o],[x,h,h,i],[c],[e,s,w],[q,i],[g,p,h],[b,c,s,s],[w,h,r,g,h,t,o,c,w],[x,h,u,i,m],[c,x,s,h],[g,q],[e,s,w], [b,q,f,s,o],[x,h], [u,i,k,t,h,o,u,x,s,h]] ], [ [[i], [i,n,v,i,t,e,d],[a], [f,r,i,e,n,d],[t,o],[m,y],[p,o,k,e,r],[g,a,m,e],[h,e],[s,a,i,d],[h,e],[d,i,d,n,t],[k,n,o,w],[h,o,w],[t,o], [p,l,a,y],[i],[t,o,l,d],[h,i,m],[h,e,d],[b,e],[p,e,r,f,e,c,t]], [[y], [y,v,a,y,d,o,i],[m], [t,u,y,o,v,i],[d,b],[l,r],[e,b,q,o,u],[s,m,l,o],[c,o],[g,m,y,i],[c,o],[i,y,i,v,d],[q,v,b,k],[c,b,k],[d,b], [e,x,m,r],[y],[d,b,x,i],[c,y,l],[c,o,i],[h,o],[e,o,u,t,o,w,d]] ] ] : end: #GR(DS,N1,L): inputs a list of words DS, a positive integer N1 and a set of {[place,letter]} finds the #list of all matching words. Try: #GR(ENG(),5, {[3,e],[5,t]}); GR:=proc(DS,N1,L) local GU,MU,A,B: GU:=DS[N1]: if L={} then RETURN(GU): fi: MU:=[]: for A from 1 to nops(GU) do if nops(GU[A])=N1 and {seq(evalb(GU[A][L[B][1]]=L[B][2]),B=1..nops(L))}={true} then MU:=[op(MU),GU[A]]: fi: od: MU: end: ALPH:=proc(): [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]: end: ALPHS:=proc(): [e, s, i, a, r, n, t, o, l, c, d, u, g, p, m, h, b, y, f, v, k, w, z, x, j, q]: end: #APPLY1(CODE,WORD,X): Given a set CODE of pairs [coded letter, real letter] and a WORD #replaces the coded letters by the real letter and otherwise by X. Try: #APPLY1({[x,a],[y,b]},[x,z,y,y,z],X); APPLY1:=proc(CODE,WORD,X) local A,XLETTERS: XLETTERS:=convert(ALPH(),set) minus {seq(CODE[A][1],A=1..nops(CODE))}: subs({seq(CODE[A][1]=CODE[A][2],A=1..nops(CODE)), seq(XLETTERS[A]=X,A=1..nops(XLETTERS))},WORD): end: #ALPHsent(C): inputs a sentence C and outputs the sequence of letters in descending frequency. #Try: #ALPHsent(C1); ALPHsent:=proc(C) local AL,CC,LU,A,X: CC:=Flatten(C): AL:=convert(CC,set): CC:=add(X[CC[A]],A=1..nops(CC)): LU:=sort([seq([coeff(CC,X[AL[A]],1),AL[A]],A=1..nops(AL))]): [seq(LU[nops(LU)+1-A][2],A=1..nops(LU))]: end: #ISGOODCODE(CODE): IS CODE a good code? Try: #ISGOODCODE({[a,b],[c,d]}); ISGOODCODE:=proc(CODE) local A: if nops({seq(CODE[A][1],A=1..nops(CODE))})=nops(CODE) and nops({seq(CODE[A][2],A=1..nops(CODE))})=nops(CODE) then true: else false: fi: end: #EXTEND(CODE,CWORD,RWORD): Given a word WORD and a partial CODE, and a real word RWORD compatible #with it, find the implied extension. Try: #EXTEND({},[a,b,c,d],[l,o,v,e]); EXTEND:=proc(CODE,CWORD,RWORD) local A,LU: if nops(CWORD)<>nops(RWORD) then RETURN(FAIL): fi: LU:=CODE union {seq([CWORD[A],RWORD[A]],A=1..nops(CWORD))}: if not ISGOODCODE(LU) then FAIL: else LU: fi: end: #EXTENDS(DS,CWORD): Given a data set DS, code word CWORD and a partial CODE finds the set of all legal extensions #Try: #EXTENDS(DS,[a,b,c,d]); EXTENDS:=proc(DS,CWORD) local LU,LU1,GU,RWORD,MU,CODE: LU:=DS[nops(CWORD)]: GU:={}: CODE:={}: for LU1 in LU do MU:=EXTEND(CODE,CWORD,LU1): if MU<>FAIL then GU:=GU union {MU}: fi: od: GU: end: #EXS1(): A list of cryptograms from the New York times. Try: #EXS1(); EXS1:=proc() [ [[x,q,w],[u],[b,u,r,p],[u,o],[x,h,h,i],[c],[e,s,w],[q,i],[g,p,h],[b,c,s,s],[w,h,r,g,h,t,o,c,w],[x,h,u,i,m],[c,x,s,h],[g,q],[e,s,w], [b,q,f,s,o],[x,h], [u,i,k,t,h,o,u,x,s,h]], [[y], [y,v,a,y,d,o,i],[m], [t,u,y,o,v,i],[d,b],[l,r],[e,b,q,o,u],[s,m,l,o],[c,o],[g,m,y,i],[c,o],[i,y,i,v,d],[q,v,b,k],[c,b,k],[d,b], [e,x,m,r],[y],[d,b,x,i],[c,y,l],[c,o,i],[h,o],[e,o,u,t,o,w,d]], [[e,q],[x,h,k,n,p,t,i,g],[i,s,p,g,g],[b,z,c,g,p,c,n,j,g,p,b],[h,p,g],[c,p,n,r,h,r,d,q],[x,d,t,v,s,i], [t,w,k,t,b,t,r,t,d,t,i,q], [h,w,m],[i,s,g],[z,w,t,i,g,m], [b,i,h,i,g,b]], #New York Times, June 4, 2020 [[o,r,b], [o,a,b,w,o,s],[o,r,d,c,x],[o,d,e,b],[o,r,b], [c,b,f,k,c,x,d,w,t],[o,k,p,x],[e,b],[s,k,n,c],[f,j,p,p],[d,h], [g,b,c,s],[d,e,q,k,c,o,j,w,o], [o,k], [n,h], [d], [a,j,h], [f,k,w,g,d,w,f,b,x]], [[t,c,n,k], [z,u,j,o], [t,u,o,m,u,j,k], [o,u,j,k,w,h,q],[r,w,h,q],[w,y],[k,u],[t,n,w,k],[j,h,k,w,b], [r,z],[r,w,e],[d,u,o,k,w,q,y],[k,c,q,h],[i,u,w,h],[n],[a,z,r],[n,h,e],[h,q,x,q,o],[a,u]], [[g,s,u,m,u],[e,u,m,u],[g,e,x],[r,u,p,r,x,h,r],[e,s,u,h],[t,p,t,u],[m,y,g,s],[t,a],[s,l,j,r,u,o,q], [x,y,g],[s,x,j,u,m,u,z],[u,b,u,m,a],[x,g,s,u,m],[p,j,u,m,l,n,p,h],[o,u,p,d,y,u],[g,u,p,j]], #New York Times, June 9, 2020 [[n],[o,e,m,w,k],[m,h],[h,l,e,e,l,q,i],[y,i],[v,n,j,j,l,a],[n],[z,w,i,y,r,l,i,i],[f,s,l,r],[k,l,m,k,j,l], [i,n,u], [q,s,l,u,e,l], [q,n,p,y,r,o],[v,n,e,l],[m,h],[z,w,i,y,r,l,i,i],[y],[n,j,f,n,u,i],[f,m,r,a,l,e]], #New York Times, June 11, 2020 [[r,z,d],[r,c,r,a,d],[q,k],[r,z,d],[k,c,a,t],[q,v,r,q,x,d,f],[m,s,b],[c,m],[y,g],[y,g,y,l,f,y,t], [q,k],[r,z,d],[x,q,q,s],[c,r], [n,y,m], [x,y,m,d,u], [q,g], [f,q,v,s,d,r],[x,q,b,m]], #New York Times, June 16, 2020 [[l,n,e,g,i,v,u,g ],[t,c,v,e,g,d],[n,d,d,o,c,x,c,v,h],[u,o],[h,u,r,c],[r,e,f,e,y,u,g,c,o], [d,g,v,j],[h,k,n,c,c],[h,u,r,c], [q,c,n,o,d,g],[d,l],[h,k,c],[j,c,e,n]], #New York Times, June 18, 2020 [[m,n,t,l,p,x,k],[h,v,o,j,p,h],[v,p,q,m,p,z],[d,p],[q,t,h,p],[o],[q,t,l],[t,b], [g,p,x,f,v,l],[l,v,p,c],[l,o,h,l,p,z],[h,t],[o,g,b,r,q],[x],[h,l,t,m,m,p,z],[z,n,x,k,j,x,k,f],[l,v,p,d] ], #New York Times, June 23, 2020 [ [r,k,b,o],[d],[r,w,g],[w],[i,d,t],[n,k,b,f,b],[r,b,f,b], [u,o,a,h],[n,k,f,b,b],[m,k,w,o,o,b,a,g],[r,k,d,m,k],[w,a,f,b,w,t,h], [k,w,t],[n,u,u],[y,p,m,k],[n,b,a,b,c,d,g,d,u,o],[n,u],[r,w,n,m,k] ], #New York Times, June 25, 2020 [ [l,c,v],[n,r,u,p,g,b,i,k],[w,k,v,f],[l,n], [m,b,d,v],[p,v,f,s,r,k],[e,n,t],[r,b,l,v,t,s,l,w,t,v],[g,s,b,o,l,b,o,m], [k,i,w,r,g,l,w,t,v],[s,t,i,c,b,l,v,i,l,w,t,v],[s,o,f],[p,w,k,b,i] ], #New York Times, June 30, 2020 [ [e,q],[k,t,s,h,t,a],[r,n,u,k],[h,t],[p,u,s,h,r,a,u], [e,u],[j,w,t,r,h],[e,q],[k,b,u,h],[w,r,h], [h,c,j,h],[u,z,k,u,k],[y,c,u,z],[b],[j,h,u],[c,b,e] ], #New York Times, July 2, 2020 [ [y,c,u],[w,p,v,g,d],[l,p,e,c,x],[k,l,x],[v,p,n,c],[r,t,j,n],[l,q,c],[f,c,t,n,p,v], [a,j,t,g],[r,j,t],[y,c,y,y,c,t,n,k,v,l],[y,r,c,r,r,c,t,n,k,v,u] ], #New York Times, July 7, 2020 [ [d,x,n,o,f,s,q],[i,b,c,a],[a,w,l,c,g],[d,x,n,o,f,s],[h,b,g,f,q],[x,s,f],[k,m,c,c,o],[x,c,i], [b,a,w,f,s],[u,f,b,u,d,f],[i,b,c,a],[a,w,l,c,g],[a,w,f,o,s,f],[h,b,g,f,q] ], #New York Times, July 9, 2020 [ [p,e],[b,z,e,v,w,k,h,z,u,p,d],[g,d,o],[w,l,o],[s,k,z,i],[x],[u],[n,k,w],[u,d], [u,q],[u,x,i],[w,k],[d,k,n,r,o,z,d],[w,l,k,g,h,l],[x,p],[u,n,d,k],[u,q],[o,h,k,p,u,q,x,u,b] ], #New York Times, July 14, 2020 [[d],[x,u,d,y,h,t],[g,l,y,d,a],[d,y],[x,u,e],[w,a,t], [h,l,w,g,n,k],[u,l,t],[y,k,h,l],[d],[y,w,a,t],[o,r],[e,v,f,h,h,l,i,a,u,r],[d,y],[x,u,e],[u,t,u,i,y,h,t]], #New York Times, July 16, 2020 [[p,k,i,b,x,p],[y,i,o],[p,f,o,p,f],[w,l,o,v],[y,k,i,o,u,f,p], [l,o],[f,t,f,y,w,b,l,y,i,t],[y,h,b,b,f,o,w],[r,k,l,y,k],[k,f,t,g,p],[w,k,f,q],[o,i,n,l,u,i,w,f]], #New York Times, July 21, 2020 [[z,s,p],[i,k,o,h],[k,f,r,t,p,b],[z,s,w,z],[g,q],[q,m,p,o,o,p,x], [g,k],[w,o,m,s,w,t,p,z,g,d,w,o],[i,b,x,p,b],[g,q],[a,i,b,z,h]], #New York Times, July 23, 2020 [[c,q,k,u],[h,t,z,x],[u,p,d,t,h],[t,n,x,v,k,u,v],[a,z,x,d,n,z,d,u,f],[z,k,u], [f,l,q,w,u,x],[p,x],[l,z,l,n,z],[x,u,g],[d,n,p,x,u,z]], #New York Times, July 28, 2020 [[c,m,n,k,b,p,m],[f,k,k,m,f,v,f,g,r,m,n],[f],[k,z,w,b,n,j],[m,g,x,w,b,n,j],[c,b,r,p,b,z,g,f,v,h], [r,f,g,p],[j,m,w,k],[h,z,l],[n,z,w,s,m],[p,j,b,n],[r,v,h,k,p,z,x,v,f,t]], #New York Times, July 30, 2020 [[c,y,l,j,y,z,g],[q,l,j,y],[o,z,l,a,g,m,l,z,y,a,o], [y,s,y,v,f,p,g],[g,t],[o,q,y,s],[k,l,a],[g,y,y],[h,a,p,y,z,x,l,o,y,z]], #New York Times, Aug.4, 2020 [ [r],[e,l,i,w],[o,j,t,c,p],[d],[n,l,y,g,j,p,g],[t,y],[w,n,p], [f,t,x,v],[h,t,l,j,i,p],[v,t,j], [w,n,p],[v,r,j,i,w],[w,r,s,p,i],[o,p,i,w],[y,r,y,p],[n,t,x,p,i],[t,v],[s,b],[x,r,v,p] ], #New York Times, Aug.6, 2020 [ [l,s,c,q,n,y,q,q,z],[f,b,z,x],[t,e,x,l,q,a],[c,q,o,x,e,a],[j,a,s,p],[x,r,s], [f,h,k,k,h,s,c],[j,k,s,r,q,a,z],[x,s],[f,e,g,q],[s,c,q],[w,s,b,c,i],[s,j],[l,s,c,q,n] ], #New York Times, Aug.18, 2020 [[w,a],[c,j,s],[m,j,v,k],[h,p,k,t,y],[g,p,t,l],[k,j],[k,y,d],[a,s,k,s,o,d],[j,v], [x,w,m,d,j,t,p,f,f,d,k,k,d],[c,j,s,o,d],[v,j,k],[o,p,d,i,i,c],[m,j,w,v,r],[w,k],[o,w,r,y,k]] , #New York Times, Sept. 27, 2022 [[b,h,g,e,j,g,m],[z,f,h],[r,b,x,i,i,h,r,z],[c,i,x,u,h,z],[s,u],[d,j,g],[r,d,i,x,g],[r,m,r,z,h,b],[s,r],[d,u,i,m],[r,i,s,v,f,z,i,m],[i,x,g,v,h,g],[z,f,x,u],[h,x,g,z,f,r],[b,d,d,u]], #New York Times, Sept. 29, 2022 [[h, d, g, y], [w, x], [c, x, o], [l, r, y], [h, d, r, a], [c, x, o], [f, p, x,z, z], [g, a], [r, e, r, n, d, g, a, y], [h, q, y, d], [g], [p, d, q, a, x, f,r, p, x, z], [l, r, r], [r, e, r, n, d, q, a, x]], #New York Times, Oct. 4, 2022 [[g], [l, y, g, b], [n, x, g, o, d, y, o, m, g, q, p], [s, j, c, y, j, d, y, l] , [d, u, y], [b, i, i, d, m, g, h], [u, x, l, l, h, y], [d, i], [m, h, i, q, p] , [u, s, f], [q, g, h, h, f], [b, o, i, w], [d, u, y], [i, e, e, i, j, y, d, f] , [c, s, y, k]], #New York Times, Jan. 10, 2023 [ [t,f,s,g,q,g],[n,s,q],[f,k,w,y,m,n,o,q],[r,f,g,q],[k,s,q,n,o,t,q,s,g], [i,q,n,r,y,r,m],[o,t,q,e],[v,n,r,r,f,o],[k,s,q,n,o,t,q],[o,t,s,f,p,m,t],[o,t,q,y,s],[i,f,p,o,t,g]], #New York Times, Jan. 12, 2023 [ [c,z], [p,s,m], [z,c,q,f], [n,k,h,w,v], [k,h], [e], [p,x,g,k,l,e,j], [b,m,l,n], [c,z], [l,e,f,b,v], [c,h,j,x], [p,s,m], [n,k,h,w], [c,z], [s,m,e,f,p,v], #[k,v,h,p], [v,g,c,f,p,k,h,w], [e], [u,q,v,p,e,l,s,m] ], #New York Times, Nov. 23, 2023 [[t,e,l,a],[l,t,j],[z,m,u,z,j,m,k],[q,j,d,r,j,m,x,y],[f,v,f,k],[w,x,y],[l,a,i,f,f],[k,d,w,u,u,f,i], [j,q,f,u,u,e],[a,j,x,f,v,z,f,f,k],[a,w,o,f],[w],[l,j,l,w,u],[j,h],[h,e,o,f],[f,v,f,k]], #New York Times, Nov. 28, 2023 [ [t,q,n], [d,o,z,n,p,w,x], [i,z,b,y], [j,q,i,w], [a,n,q,z,m,g,z,x], [w,v,y,z,w,y,n,i], [i,b,p,r], [n,q,g], [p], [a,y,d,z,s,i,y], [p,w], [n,y,i,y,j,a,o,y,i], [w,v,y], [f,s,j,a,y,n], [q,f,y] ] ] : end: #EXS2(): A list of pairs [SOURCE,CODED]. Try: #EXS2(); EXS2:=proc() [ [ [[b,o,y],[i],[w,i,s,h],[i,d],[b,e,e,n],[a],[f,l,y],[o,n],[t,h,e],[w,a,l,l],[y,e,s,t,e,r,d,a,y],[b,e,i,n,g],[a,b,l,e],[t,o],[f,l,y], [w,o,u,l,d],[b,e], [i,n,c,r,e,d,i,b,l,e]] , [[x,q,w],[u],[b,u,r,p],[u,o],[x,h,h,i],[c],[e,s,w],[q,i],[g,p,h],[b,c,s,s],[w,h,r,g,h,t,o,c,w],[x,h,u,i,m],[c,x,s,h],[g,q],[e,s,w], [b,q,f,s,o],[x,h], [u,i,k,t,h,o,u,x,s,h]] ], [ [[i], [i,n,v,i,t,e,d],[a], [f,r,i,e,n,d],[t,o],[m,y],[p,o,k,e,r],[g,a,m,e],[h,e],[s,a,i,d],[h,e],[d,i,d,n,t],[k,n,o,w],[h,o,w],[t,o], [p,l,a,y],[i],[t,o,l,d],[h,i,m],[h,e,d],[b,e],[p,e,r,f,e,c,t]], [[y], [y,v,a,y,d,o,i],[m], [t,u,y,o,v,i],[d,b],[l,r],[e,b,q,o,u],[s,m,l,o],[c,o],[g,m,y,i],[c,o],[i,y,i,v,d],[q,v,b,k],[c,b,k],[d,b], [e,x,m,r],[y],[d,b,x,i],[c,y,l],[c,o,i],[h,o],[e,o,u,t,o,w,d]] ], [ [[f,r,a,n,k,l,i,n],[d,e,l,a,n,o],[r,o,o,s,e,v,e,l,t],[i,s],[t,i,m,e],[m,a,g,a,z,i,n,e,s],[o,n,l,y],[t,h,r,e,e],[t,i,m,e], [p,e,r,s,o,n],[o,f],[t,h,e],[y,e,a,r]], [[l,n,e,g,i,v,u,g ],[t,c,v,e,g,d],[n,d,d,o,c,x,c,v,h],[u,o],[h,u,r,c],[r,e,f,e,y,u,g,c,o], [d,g,v,j],[h,k,n,c,c],[h,u,r,c], [q,c,n,o,d,g],[d,l],[h,k,c],[j,c,e,n]] ] ]: end: #EXS3(): A collection of sayings to experiment with. Try: #EXS3(); EXS3:=proc(): [ [ [a,l,l], [t,h,e], [w,o,r,l,d], [i,s], [a], [s,t,a,g,e], [a,n,d], [t,h,e], [p,e,o,p,l,e], [a,r,e], [a,c,t,o,r,s] ]] : end: #ISPROMISING(DS,CODE,CR): Given a data-set, DS, a CODE and a cryptogram #decides whether it is promising. Try #ISPROMISING(ENG(),[[X,a,a,a]],X); ISPROMISING:=proc(DS,CODE,CR) local A,PCR,X: PCR:=APPLY1(CODE,CR,X): for A from 1 to nops(PCR) do if not ISPROMISING1(DS,PCR[A],X) then RETURN(false): fi: od: true: end: #ISPROMISING1(DS,W,X): Given a data-set DS, and partiallly filled words with X, decides whether is has exensions ISPROMISING1:=proc(DS,W,X) local GU,A,N: GU:={}: N:=nops(W): for A from 1 to N do if W[A]<>X then GU:=GU union {[A,W[A]]}: fi: od: if GR(DS,N,GU)=[] then false: else true: fi: end: #COMPWS(DS,WORD,X): Given a data set DS, and a partial tentative word where the unknowns are #given by X, outputs the set word in the data-base such that it fits the description #Try: #COMPWS(ENG(),[l,X,v,X],X); COMPWS:=proc(DS,WORD,X) local A,S,N1: N1:=nops(WORD): S:={}: for A from 1 to N1 do if WORD[A]<>X then S:=S union {[A,WORD[A]]}: fi: od: GR(DS,nops(WORD),S): end: #CHILDREN(DS,CR,CODE): Given a cryptogram C and a current partial code, find all the possible extenions #if none exits, it returns FAIL. Try: #CHILDREN(ENG(),EXS()[2][2],{}); CHILDREN:=proc(DS,CR,CODE) local X,CR1,SI,A,ALUF,LU,W,CODE1,GU: CR1:=APPLY1(CODE,CR,X): if not member(X,{op(Flatten(CR1))}) then RETURN({CODE}): fi: SI:=coeff(convert(CR1[1],`+`),X,1): ALUF:=1: for A from 2 to nops(CR) do if coeff(convert(CR1[A],`+`),X,1)>SI then ALUF:=A: SI:=coeff(convert(CR1[ALUF],`+`),X,1): fi: od: LU:=COMPWS(DS,CR1[ALUF],X): W:=CR[ALUF]: GU:={}: for A from 1 to nops(LU) do CODE1:=EXTEND(CODE,W,LU[A]): if CODE1<>FAIL then if ISPROMISING(DS,CODE1,CR) then GU:=GU union {CODE1}: fi: fi: od: RETURN(GU): end: KIDS:=proc(DS,CR,SETCODE) local CODE: {seq(op(CHILDREN(DS,CR,CODE)), CODE in SETCODE)}: end: SOLVEC1OLD:=proc(DS,CR) local S,S1,S2: S:={{}}: S1:=KIDS(DS,CR,S): while S<>S1 do S2:=KIDS(DS,CR,S1): S:=S1: S1:=S2: od: S1: end: #SOLVEC(DS,CR): inputs a cruptogram puzzle C, in the data-set DS, and finds a solution. Try: #SOLVEC(ENG(),EXS()[1][2]); SOLVEC:=proc(DS,CR) local SOL,A,GU,B,X: SOL:=SOLVEC1(DS,CR): if SOL={} then RETURN(FAIL): fi: for A from 1 to nops(SOL) do GU:=APPLY1(SOL[A],CR,X): print(``): print(seq (convert(cat(op(GU[B])),string),B=1..nops(GU))): print(``): od: end: #JOIN(S1,S2) two sets of Codes S1 and S2 finds their joining. Try: #CR:=EXS1()[7]; JOIN(EXTENDS(ENG(),{},CR[1]),EXTENDS(ENG(),{},CR[2]) ): JOIN:=proc(S1,S2) local C1,C2,LU,MU: LU:={}: for C1 in S1 do for C2 in S2 do MU:=C1 union C2: if ISGOODCODE(MU) then LU:=LU union {MU}: fi: od: od: LU: end: SOLVEC1:=proc(DS,CR) local GU,A,ALUF,CR1,SI: CR1:=CR: GU:={{}}: while CR1<>[] do ALUF:=1: SI:=nops(CR1[1]): for A from 2 to nops(CR1) do if nops(CR1[A])>SI then ALUF:=A: SI:=nops(CR1[ALUF]): fi: od: GU:=JOIN(GU,EXTENDS(DS,CR1[ALUF])): CR1:=[op(1..ALUF-1,CR1),op(ALUF+1..nops(CR1),CR1)]: od: GU: end: #MakeCR(P): inputs a saying, and outputs a random cryptogram whose solution it is. Try: #MakeCR(P1): MakeCR:=proc(P) local gu,pi,i: gu:=ALPH(): pi:=randperm(nops(gu)): subs({ seq( gu[i]=gu[pi[i]], i=1..nops(gu))},P): end: #GR1(DS,N1,L): Like GR(DS,N1,L), but only those without the information given by L. GR1:=proc(DS,N1,L) local S, GU,W,A,LU,W1: S:={seq(L[A][1],A=1..nops(L))}: GU:=convert(GR(DS,N1,L),set): LU:={}: for W in GU do W1:=[]: for A from 1 to N1 do if not member(A,S) then W1:=[op(W1),W[A]]: fi: od: LU:=LU union {W1}: od: LU: end: #BT(DS,N1,LL): Solves a Brain Tickler problem. For the Jan. 6, 2023 try: #BT(ENG(),6,[{[1,e],[2,x]},{[1,s],[6,y]},{[5,a],[6,l]}]); BT:=proc(DS,N1,LL) local A,GU: GU:=GR1(DS,N1,LL[1]): for A from 2 to nops(LL) do GU:=GU intersect GR1(DS,N1,LL[A]): od: GU: end: #ANAG2(DS,W): Finds all the pairs [W1,W2] such that W1 and W2 in the database DS are words and [W1,W2] is an anagram of W, try: #ANAG2([i,r,i,s,h,l,a,c,e]); ANAG2:=proc(DS,W) local A,GU,GU1,L,LU: L:=nops(W): GU:=convert(permute(W),set): LU:={}: for GU1 in GU do for A from 2 to L-2 do if member([op(1..A,GU1)],convert(DS[A],set)) then if member([op(A+1..L,GU1)],convert(DS[L-A],set)) then LU:=LU union {[[op(1..A,GU1)], [op(A+1..L,GU1)]]}: fi: fi: od: od: LU: end: #OVERLAP(DS,W1,W2,A): Given two words W1 , W2, and a data-set DS, as well as a positive integer A, finds all V such that W1V and VW2 are words. Try: #OVERLAP(ENG(),[f,l,e],[e,l,f],2); OVERLAP:=proc(DS,W1,W2,A) local GU1,GU2,A1,W: GU1:=GR(DS,nops(W1)+A,{seq([A1,W1[A1]],A1=1..nops(W1))}): GU2:=GR(DS,nops(W2)+A,{seq([A+A1,W2[A1]],A1=1..nops(W1))}): GU1:={seq([op(nops(W1)+1..nops(W1)+A,W)],W in GU1)}: GU2:={seq([op(1..A,W)],W in GU2)}: GU1 intersect GU2: end: #RevPuz(DB,K,L): All the pairs of words [w1,w2] such that w1 has K letters that contains the letter L, and w2 is the reverse of the word that #is obtained by deleting L. For the Septl 20, 2023, Brain Tickler Puzzle of the New York Times. Try: #RevPuz(ENG(),5,l); RevPuz:=proc(DB,K,L) local MU,GU,W1,W2,B,LU,A: MU:=DB[K]: LU:=convert(DB[K-1],set): GU:=[]: for A from 1 to nops(MU) do W1:=MU[A]: if member(L,convert(W1,set)) then for B from 1 while W1[B]<>L do od: W2:=[op(1..B-1,W1),op(B+1..nops(W1),W1)]: W2:=[seq(W2[K-B],B=1..K-1)]: if member(W2, LU) then GU:=[op(GU),[W1,W2]]: fi: fi: od: GU: end: #ME(DB,i,j): all the catenations of DB[i] and DB[j]. Try: #nops(ME(ENG(),2,2)); ME:=proc(DB,i,j) local GU1,GU2,A1,A2: GU1:=DB[i]: GU2:=DB[j]: {seq(seq([op(GU1[A1]),op(GU2[A2])],A2 in GU2),A1 in GU1)}: end: #NEIS(DB,W): all the neighbors of the word W in the database DB. Try: #NEIS(ENG(),[s,m,a,r,t]); NEIS:=proc(DB,W) local K,AL,W1,LU,A,B: K:=nops(W): if not member(W, convert(DB[K],set)) then RETURN(FAIL): fi: LU:={}: AL:=ALPH(): for B from 1 to K do for A from 1 to nops(AL) do if AL[A]<>W[B] then W1:=[op(1..B-1,W),AL[A],op(B+1..K,W)]: if member(W1, convert(DB[K],set)) then LU:=LU union {W1}: fi: fi: od: od: LU: end: #SULAM(DB,W,K): all the ladders of size K that start with W. Try: #SULAM(ENG(),[s,m,a,r,t],5); SULAM:=proc(DB,W,K) local MU,GU,MU1,W1,KU,KU1: option remember: if K=1 then RETURN({[W]}): fi: MU:=SULAM(DB,W,K-1): GU:={}: for MU1 in MU do W1:=MU1[-1]: KU:=NEIS(DB,W1): for KU1 in KU do if not member(KU1, convert(MU1,set)) then GU:=GU union {[op(MU1),KU1]}: fi: od: od: GU: end: #SuperW(DB,W): all the words containing w, try: APR(ENG(),[a,p,r]); SuperW:=proc(DB,W) local K,A,S,S1,V,B: K:=nops(W): S:={}: for A from nops(W)+1 to nops(DB) do S1:=convert(DB[A],set): for V in S1 do for B from 1 to A-nops(W)+1 do if [op(B..B+K-1,V)]=W then S:=S union {V}: fi: od: od: od: S: end: