Daily Cipher
A Tale of 2 Secrets › Forums › T.E.M.P.E.S.T. › Daily Cipher
- This topic has 58 replies, 10 voices, and was last updated 1 week ago by Puzzling_Pelican.
-
AuthorPosts
-
9th January 2026 at 9:50 am #115115Robb27Participant
@Puzzling_Pelican
If you are still checking the forum (?) I just can’t get your transposition for 9A. I am not sure how many different permutations I have tried based on the factors of the length of the string. I know it is will in excess of ~40 million ( that’s the permutations for a factor length of 11). The hints haven’t helped as I pretty much know what I needed to do. Any other pointers would be welcome!9th January 2026 at 12:58 pm #115128Puzzling_PelicanParticipant@Robb27
One of the ~5000 permutations should work for the columnar transposition.
The intermediate text starts with “AA DF AF AG”.9th January 2026 at 4:40 pm #115132Robb27Participant@Puzzling_Pelican
Thank-you. I’m not sure how I missed the correct ordering at that key length, particularly as the python code is quite simple. Anyway, after a short investigation with Excel, rather than python, I had it. Now 9B!11th January 2026 at 2:02 pm #115143ChinchinchillaParticipantCan someone please help me on Challenge 5B, I don’t understand how to get the cipher out of polybius form
11th January 2026 at 6:03 pm #115146BobDParticipantI may have missed the point of the previous posts, but …….
9A was a 7 column Vigenère, together with a reversal of the text.
5B was a straightforward keyword substitution. The crib I used was “My dear”.11th January 2026 at 6:03 pm #115148Robb27Participant@Chinchinchilla
Have a look at the frequency of number pairs, this may give you a clue.12th January 2026 at 8:49 pm #115159_madness_Participant@Puzzling_Pelican
I promised to reveal this one secret to you after NCC ended, which it has. To get the 10B plaintext, I used the oracle that you provided: the feedback on submissions. For each trigram that it solved for me, there were 6 or 12 trigrams whose plaintexts were now known to me (they don’t all appear in the text). Using the oracle and reconstructing what I could, and guessing where I could, eventually I had the whole text. To get the key, I assumed that 0 and 1 were contiguous (there were reasons for this: like it also meant that L and M were contiguous). That allowed me to build up rows of the key. The last bit was to arrange the rows in the right order.
14th January 2026 at 9:12 pm #115165Robb27Participant@BobD You are referring to the main NCC challenges. Through this specific ‘Daily Cipher’ thread @Puzzling_Pelican was running some additional challenges. If you look back to the early pages of this thread you will find them.
11th February 2026 at 10:45 am #115348_madness_Participant@Puzzling_Pelican
I was working on a description and Python code for the Puzzling Pelican Playfair
(P³) cipher, but kept getting 241 erroneous trigrams when I decrypt the 10B ciphertext.
Some of these are due to 1-1-1 triangles that I have yet to fix. But others, like
TXR -> NSE and IFX -> ECA do not make sense to me. My method decrypts them
as ORX and FIZ respectively, by trying to put the centers of the two triangles
as close as possible to each other. One of us is making a mistake; is it me?Also, I have about a megabyte of nice graphics for the grid of this cipher.
How shall I send them to you (if you want them)?13th February 2026 at 9:31 am #115355Puzzling_PelicanParticipant@madness
The graphics would be amazing to see, could you try sending them to Harry and he would be able to forward it on towards me? (@Harry would this be possible?)
Also, I love the name P³ !Regarding some oddities about how the cipher chooses to encrypt, I think a few of them may simply come down to how I implemented it in code a while ago.
If you are certain that your version of the code is closer to how I intended the cipher to work (like with the 1×1 and where your code has the centers closer than my code mistakenly places them), then please do fix the ciphertext on the archive to reflect this. I would prefer a slightly altered ciphertext to a slightly flawed cipher. I appreciate the effort you have put in to reasearching this cipher and look forward to seeing the results.
This is the original code I wrote for this, hopefully you can make some sense out of it (I still can’t remember how all of it works).import math import typing import re TYPE_COORDS = typing.Tuple[float, float] TYPE_GRID = typing.Dict[TYPE_COORDS, str] grid: TYPE_GRID = {} invalid_points = set() def generate_spiral(limit): """ Generate a spiral on a triangular grid. """ directions = [ (1, 0), # right (0.5, 1), # down-right (-0.5, 1), # down-left (-1, 0), # left (-0.5, -1), # up-left (0.5, -1), # up-right ] dir_between_circles = (-0.5, -1) # up-left after each hex path = [] x, y = 0.0, 0 # start dir_idx = 0 # start facing right steps_in_leg = 1 steps_taken = 0 # center path.append((x, y)) x += dir_between_circles[0] y += dir_between_circles[1] for _ in range(limit - 1): # Move in current direction dx, dy = directions[dir_idx] x += dx y += dy steps_taken += 1 # Snap x to integer or half-integer depending on row if y % 2 == 0: x = round(x) # even row -> integer x else: x = round(x - 0.5) + 0.5 # odd row -> half-integer x coord = (x, y) path.append(coord) # Spiral logic: after finishing a leg, turn clockwise if steps_taken == steps_in_leg: steps_taken = 0 dir_idx = (dir_idx + 1) % 6 # completed full hexagon if dir_idx == 0: steps_in_leg += 1 x += dir_between_circles[0] y += dir_between_circles[1] return path def generate_grid(key: str) -> TYPE_GRID: """Generates a grid from a key string.""" grid: TYPE_GRID = {} padding = "abcdefghijklmnopqrstuvwxy!#$%&()*+,-./:;<=>?@[\]^_{}~£z" key += padding spiral: typing.List[TYPE_COORDS] = generate_spiral(len(key)) for i in range(len(key)): col, row = spiral[i] grid[(col,row)] = key[i] return grid def get_coord_of_letter(letter: str, grid : TYPE_GRID) -> TYPE_COORDS: """Finds the coords that map to a specific letter in the grid.""" for coords, l in grid.items(): if l == letter: return coords def get_letter(coords: TYPE_COORDS, grid : TYPE_GRID) -> str: """Returns the letter at a position in the grid.""" if coords not in grid: invalid_points.add(coords) return grid.get(coords, "") def get_center_of_traingle(a: TYPE_COORDS, b: TYPE_COORDS, c: TYPE_COORDS) -> TYPE_COORDS: """Returns the center of a triangle generated by taking an avarage.""" return ((a[0] + b[0] + c[0]) / 3, (a[1] + b[1] + c[1]) / 3) def _is_whole_num(value: float) -> bool: """Returns whether a float is an intiger, compensates for floating point error""" return abs(value - round(value)) < 1e-9 def round_midpoint(p: TYPE_COORDS) -> TYPE_COORDS: """Round the point to either the grid or directly between 2 points. 3 cases: - On an intersection of axes: stays the same - In the middle of a cell (not on any axes): Moved vertically up or down (The original version used for 10B ignored this case because of broken code) - On 1 axis: rounded to the middle of that axis (half way between nearest points on axis) """ x, y = p # Check if it is on an intersection if _is_whole_num(y): # y must be an intiger # if even row, x is int, if odd, x is int+0.5 if (int(y) % 2 == 0 and _is_whole_num(x)) or (int(y) % 2 == 1 and (_is_whole_num(x - 0.5))): # Leave midpoint as is return (x, y) # Check if it is in center of cell # The original code written for this case was broken so the original 10B encrypt ignored this and treated it the same as the axis case. # Check if the centerpoint is on the i axis if _is_whole_num(y): # round the int+0.5 if on even axis and int if odd (halfway between 2 points) if int(y) % 2 == 0: x = round(x + 0.5) - 0.5 else: x = round(x) return (x, y) # Must be on either the j or k axis # y should be rounded to int+0.5 # x should be rounded to int+0.25 or int+0.75 y = round(y + 0.5) - 0.5 x = round(2 * x + 0.5) / 2 - 0.25 return (x, y) def reflect_point(p: TYPE_COORDS, mid: TYPE_COORDS) -> TYPE_COORDS: """Reflects a point in the midpoint. A in M goes to A + 2(A->M).""" x, y = p dx = mid[0] - x dy = mid[1] - y nx = x + 2 * dx ny = y + 2 * dy return (nx, ny) def map_points(a: TYPE_COORDS, b: TYPE_COORDS, c: TYPE_COORDS) -> typing.Tuple[TYPE_COORDS, TYPE_COORDS, TYPE_COORDS]: # get midpoint mid = round_midpoint(get_center_of_traingle(a, b, c)) # reflect each point in midpoint na = reflect_point(a, mid) nb = reflect_point(b, mid) nc = reflect_point(c, mid) return na, nb, nc def map_trigram(a: str, b: str, c: str, grid : TYPE_GRID) -> typing.Tuple[str, str, str]: point_a = get_coord_of_letter(a, grid) point_b = get_coord_of_letter(b, grid) point_c = get_coord_of_letter(c, grid) new_point_a, new_point_b, new_point_c = map_points(point_a, point_b, point_c) na=get_letter(new_point_a, grid) nb=get_letter(new_point_b, grid) nc=get_letter(new_point_c, grid) return na, nb, nc def display_grid(grid: TYPE_GRID, point_spacing: int = 40, margin: int = 50): """Displays the key using tkinter. AI generated but works""" import tkinter as tk import math root = tk.Tk() root.title("Triangular Lattice Viewer") # Extract bounds of grid xs = [x for (x, y) in grid.keys()] ys = [y for (x, y) in grid.keys()] min_x, max_x = min(xs), max(xs) min_y, max_y = min(ys), max(ys) width = int((max_x - min_x + 2) * point_spacing) + 2 * margin height = int((max_y - min_y + 2) * (math.sqrt(3)/2) * point_spacing) + 2 * margin canvas = tk.Canvas(root, bg="white", width=width, height=height) canvas.pack(fill=tk.BOTH, expand=True) def grid_to_pixel(col, row): """Convert triangular lattice coords to pixel coords.""" px = (col - min_x) * point_spacing + margin py = (row - min_y) * (math.sqrt(3)/2) * point_spacing + margin return px, py # Draw optional mesh lines directions = [ (1, 0), (0.5, 1), (-0.5, 1), (-1, 0), (-0.5, -1), (0.5, -1) ] for (col, row), letter in grid.items(): x, y = grid_to_pixel(col, row) # Draw point r = 3 canvas.create_oval(x-r, y-r, x+r, y+r, fill="black") # Draw letter canvas.create_text(x, y-12, text=letter, font=("Arial", 10, "bold")) # Draw connecting lines for dx, dy in directions: neigh = (col+dx, row+dy) if neigh in grid: nx, ny = grid_to_pixel(*neigh) canvas.create_line(x, y, nx, ny, fill="black") root.mainloop() def gen_key(word: str) -> str: alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +"0123456789" padding = alpha[alpha.index(word[-1]):] + alpha[:alpha.index(word[-1])] # padding = alpha key = "" for l in word + padding: if l not in key: key += l return key key = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" key="RLSYXQKFGMTZ432WPJEABCHNU0598761VOID" key = gen_key("CONTAIN") grid = generate_grid(key) display_grid(grid) def encrypt(text, grid): """Encrypts (or decrypts since encryption and decryption are symmetrical) text using a grid.""" res = "" tri = "" text = list(text) padd_1 = "0" padd_2 = "1" while text: l = text[0] if l in tri: if len(tri) == 1: tri += padd_1 if len(tri) == 2: if padd_1 in tri: tri += padd_2 else: tri += padd_1 else: tri += l text.pop(0) if len(tri) == 3: ntri = map_trigram(*tri,grid) res += "".join(ntri) tri = "" return res text = """DEARCOUNCILMEMBERSIAMWRITINGTHISURGENTMES0SAGETOBRINGTOY0OURAT0TENTIONAMAT0TEROFUTMOSTIMPORTANCEREGARDINGTHELIGHT0HOUSEREC0ENTEV0ENTSHAVEFORCEDUSINTOASITUATIONWEHAVELONGWORKEDTOPREVENTAGENTSHAR01RYANDJODIEHAVEUNCOVEREDTHE0HIDDENLAYERSOFTHELIGHTHOUSESOPERATIONSTHOUGHWEHAVETAKENGREATCARETOENSURETHATOURT0RUEPURPOSER0EMAINSOBSCUREDTHEIRINVESTIGATIONHASPEN0ETRATED01DE0EP0ERTHANANYPREVIOUSINTERNALTHREAT01THEYHAVEPIECEDTOGETHERTHELIGHTHOUSE0SROLENOTASA0SIMPLERESEARCHANDARCHIVALINSTITU0TIONBUTASAFUL01LYOPERATIONALEXTENSIONOFBOSSINTELLIGENCEOPERATIONSTASKEDWITHACQUIRINGSENSITIVEDOCUMENTSINFILTRATINGEXTERNALREPOSITORIESAND0DELIVERINGACTIONABLEINTEL01LIGENCEUNDERTHEGUISEOFHISTORICALSTUDYTHEIMPLICATIONSOFTHEIRDISCOVERYCAN0NOTBEOVERSTATEDTHEIRKNOWLEDGENOWTOUCHESEV0ERYLEVELOFOURWORKFROMPROJECTSENTINELSEARLYSTAGEMONITORINGCAPABILITIESTO0THECONSTRUCTIONOFTHENEWCOMPUTATIONALINFRASTRUCTURECAP0ABLEOFPROCESSINGVOLUMESOFINTELLIGENCEPREVIOUSLYCONSIDEREDUNAT01TAINABLETHEYHAVEIDENTIF0IEDPATTERNSINPERSON01NELAS0SIGNMENTSFINANCIALTRANSACTIONSANDOPERATIONALDIRECTIVESTHATLINKTHELIGHTHOUSEEXPLICITLYTOBOSSANDHAVEBEGUNTOTRACETHECHAINOFCOMMANDTHATUNDERPINSOURCOVERTOPERATIONSIT0ISCLEARTHATHAR0RYANDJODIESPRESENCEWITHINOURSPHERECAN01NOLONGERBETOLERATEDWITHOUTSIGNIF0ICANTRISKTHEIRCURIOSITYWHILECOM01MENDABLEINORDINARYCIRCUMSTANCESNOWCONSTITUTESADIRECT01THREATTO0THEINTEGRITYOFTHELIGHTHOUSEANDBYEXTENSIONBOS0SWEMUSTACTDECISIVELYTOC0ONTAINTHEEXPOSUREANDENSURETHATTHEKNOWLEDGETHEYHAVEACQUIRED01DOESNOTPROPAGATEB0EYONDWHATCANBECONTROLLEDEF0FECTIVEIMMEDIATELYTHECOUNCILMUSTCONSIDERAMULTIPRONGEDCONTAINMENTS0TRATEGYALLFILESANDDIGITALRECORDSAC01CESSEDBYTHEAGENTS0SHOULDBESECUREDANDWHEREAP01PROPRIATEREMOVEDFROMSTANDARDOPERATIONALCHAN01NELSANYTRACESOFTHEIRACTIVITYONINTERNALCOM0MUNICATION01NETWORKSMUSTBECAREFULLYSCRUB01BEDENSURINGTHATNORESIDUALDATACOULDHINTAT01THESCOPEOFTHEIRDISCOVERIESPERSON0NELWHOMAYHAVEINADVERTENTLYGUIDEDORINFLUENCEDTHEAGENTSMUSTBEDISCRE0ETLYREAS0SIGNEDANDAC0CESSPROT0OC0OLSMUSTBEREINFORCEDTOPREVENTFURTHERBREACHESITISEQUAL01LYIMPORTANT0TOMAN0AGETHEAGENTSTHEMSELVESWHILETHEIRLOYALTYANDSKIL01LSARE0RECOGNIZEDTHEIRCONTINUEDPROXIMITYTOCRITICALOPERATIONSCAN0NOTBEAL01LOWEDCONTROLLEDENGAGEMENTMONITOREDCOM01MUNICATIONA0NDCAREFULLYORCHESTRATED0DISINFORMATIONWIL0LBEREQUIREDTOPREV0ENTTHEMFROMRECONSTRUCTINGTHEFUL01LSCOPEOF0OUROPERATIONSTHEIRUNDERSTANDINGOFPROJECTSENTINELTHESUPERCOMPUTERANDOURCOVERTDOCUMENTACQUISIT0IONMUSTBEDELIBERATELYOBFUSCATEDWHILEPRESERVINGTHEFUNCTIONALITYOFTHELIGHTHOUSEFOR0ONGOINGMIS01SIONSTHECOUNCILMUSTALSOCONSIDERTHEBROADERIMPLICATIONS0SHOULDHARRYANDJODIEB0EALLOWEDTOLEAVEWITHANYDEGREEOFUNMIT0IGATEDKNOWLEDGETHERESULTINGEXPOSUREWOULDCOMPROMISEDECADESOFINTEL01LIGENCEWORKANDENDANGERTHELIVESOFCOUNTLES01SOPERATIVESAT01THESAMETIMETHEMORALANDPSYCHOL0OGICALWEIGHTOFTHESEACTIONSCAN0NOTBEIGNOREDWEOPERATEINTHESHADOWSNOTFORCONVENIENCEBUTBECAUSETHEWORLDWEPROTECTRELIESUPONOURDISCRETIONTHISREALITYREQUIRESDECISIONSTHATARENOTWITHOUTPERSONALORETHICALCOSTWEHAVESURVIVEDTHREATSTOTHELIGHT0HOUSEBEFORE0EXTERNAL0ADVERSARIESINTERNALDIS01SENTANDUNFORES0E01ENLEAKSBUT01THISREPRESENTSATHREATUNLIKEANYWEHAVEFACEDTHEAGENTSINGENUITYAND0DETERMINATIONCOMBINEDWITHT0HEIRPARTIAL0LOYALTYTOBOSSCREATEASCENARIOWHER0EANYDELAYINACTIONCOULDBECATASTROPHICTHECOUNCILMUSTACTWITHPRECISIONDISCRETIONA0NDUNITYHESITATIONISALUX0URYWENOL0ONGERPOS0SE0S01SFINALLYIREMINDYOUTHAT01THESURVI0VALOFTHELIGHTHOUSEANDTHESECURITYOFBOS01S01SWIDEROPERATIONSREST0SUPON0OURABILITYTOMANAGEBOTHT0HESITUATIONANDPERCEPTIONTHEAGENTSMUSTNEVERFULLYGRASPTHECONSEQUENCESOFTHEIRDISCOVERIESTHEYMUSTBEGUIDEDINTOAN0AR0RATIVETHATSATISFIESTHEIRCURIOSITYWITHOUTGRANTINGFULLACCESSTOOURIN0NERWORKINGSAL01LMEASURESTAKENSHOULDPRESERVETHEOPERATIONALFACADEOFTHELIGHTHOUSEWHILE0ELIMINATINGTHEIM01MEDIATERISKTHEYPOSETIMEISOFTHEES0SENCETHECOUNCILISDIRECTEDTOCONVENEIMMEDIATELYAUTHORIZETHECONTAINMENTMEASURESHEREINDESCRIBEDANDOVERSE01ETHEIREX0ECUTIONWITHOUTDELAYOURACTIONSMUSTBEMETICULOUSTHOROUGHANDWITHOUTHESITATIONTHEFUTUREOFTHELIGHT0HOUSEANDTHEPRESERVATION0OFDECADESOFSTRATEGICOPERATIONSDEPENDSUPONTHEDECISIONSMADEINTHESECOMINGHOURSTHEAGENTSHAVESTUMBLEDUPONATRUTHT0HATCANNOTBELEFTUNCHECKEDIT0ISNOW0OURDUTYTOENSURETHAT01THELIGHT0HOUSEANDTHELEGACYOFITSFOUNDINGME0MBERSCONTINUESUNBROKENSECUREFROMDISCOVERYANDCAP0ABLEOFFULFILLINGITSPURPOSEINTHISTHERECANBENOCOMPROMISEWITHUNWAVERINGRESOLVETRINITY01""" text = re.sub("[^A-Z0-9a-z]*","",text.upper()) print(encrypt(text,grid)) text="XWmCR OCNUw 10Pm0 5WT1M AQXUC VAArX 7CP?N I12V2 HVGTS OTE2X UGNYH PTSQN I0TWN EPNA1 QVI0T NREW6 A2VIA OUO2M XOSXW O?INU EQXHO GWZYJ MCJX7 XZT5W 1YWNE WIHDN EWHSC oWBOC R9VnC 7OCXN AUOAU NSCPG YDBXN UI1NZ pG92O VDVX4 XNEYX NNEWH SCKQP GOCG0 BX2VZ WFWUE OSNCR EWXnA KFVE0 TVnX0 15WTF OAAKo GIAIS YTW6P OSQFN PNANT S7XZX ErZWF XNWHE KA6FC WXORA OTERT XTD6H TYSVC Z2SDT 67QNS OP2GV MEI7O C9RVS PTWXn T0FAS PTSEH FCCIT YZSRI NPYBR NEWXC wTXZA mMYTR ENNAH TYNVX 4PUTP C7EWN TO6XK PFQNL CAGWZ ZAHAO DWPXW XnpNI GWZGI SwXZA Xr7XZ H2VQO RB2ZX CNJPN LQNYW MW5TQ NFHCZ ECBHI RT0CN PLAOU CZ9PN A9SVN UXWNG 0LKT2 JV4XC ITTCS n0ZWN EISCA XRR9V C7OZ1 DYJMO XWQXW QFNPN ANTSP JUWXE YJCQP AP7TX HOXRT AUODY CQWVZ lQNST WYOIT LXSOX HOTWE RET2N JQWXA UOPIR OFVY1 B0ImD YCASP CYGPN AW9CX wZEWN 0LKYJ MOXWS XWCN= GWZSH WXRW0 AGCRN ZOPQU 0BENA HTMAE 0C1AC ISCPX W6GWZ 9EQSI ODTSY RCCZV CTOAN nCREX NUnWX GWZ1t OTWOm I0VAp WONNP SVIqI HDPpN lPZ2B Y6WAT 4NrV2 12SRP QW0GV ESACV Z2BFO VJN3X NUIK> CPSRN TXHOI PAT0W TILVQ Y1ZNG WZSNO CRTAV NSCPF OAVIG NTDMO 2ANUP NA0PV WYOT6 C6VOV NAERV 1ZCCL BCoNR PQVRX C7OSZ FO}CR XWOWY Z1DYJ MOXW4 VXCYD UONX1 JNOCm AT=NC ATULC AICTW 9CD1Z EHFVX HTmAN EWY1X mTAXC INREO C7AWQ OQRLO CZ2BP JNHTR ZD2NS TOWYN AT0LA OXSCA SAITN OCBEC XWQXS OSCPA DLVFQ AITTS EHTYL TIZ9I AKoGI AISYT W6IAo C1LIL TOIYR 9VASC JWFD9 WT9pC OTOXS ECXVI FCZYA XR21N VQ1ZF BUNAn TVIOR OCNPT SDTST RNV4X CITNO CA0TS IOELZ GISYH TQZSG OCG0B X2VRX BW5TO XWCAD JCYSU OOQ6U PpIFX LOC1I UYZRS nCOTE VaHWX CCTlI SYN7V XOHY1 XTACO RTPKS GWZOZ PPT7C ISXVA 1JYQT X0MLD 2ZTlX XwZRS NPBXC GOPOZ PLVXN UXWOC ONOVW NTS9N AVSEX 0EERV LCAIS GCWX1 ZNGWZ VACIN ?XZCF OAAKo GIAIS YTW6B ECFlW WETOC 7BVOI 0SoTN 82PIC AnXWO SIDYC X1KIP STCOC TZGWZ IAoUN OFQNn TV7US ERNTY HGWZ7 1IZmI GDFGW ZZAHX NBSVP VFQwT XCnNC ONQNA ICQNX YCZlI TpDNV TYHTN AANDT CO126 mI0ZA nTAoC VIMAE <I0TC IKoZG WZSNP ICNOC }AONN OCmAT 03N09 PROIY ZRTAn TCOCT ZD2ZP ZUOXS pYW10 XXMZB 2HBEC JoTTI CVHaR OCOE9 LPIVR XnUNA 9WWZF VApPZ UZ6AZ k2TUn SBX=N CBECG DYFQN 0PIRP QOIRW XCZbV DTSCU =2SMC NAQUE QWBQF NPNA0 PVHCZ LOCZ2 BASCS CFXFI XW6GW ZOZQA ITIVC SXAVA CRET1 T0LCQ 91PTA CPNAL OCENW 4NTRv CNV7A NDNFQ QJBVQ JSTPL VWEBW RTXPT 7GNYT YHRSN QYVCF BDLAI CAILU 0VEAC NLCAG WZCSN WQXAG WQVFQ 9XNTP QFVRX B5WTI 1SZ2B IUFF0 1VXHP WYBCX RENNE WpJ0X kONCn ASPQB JOXWW XnWZF VAp20 VNV7E BWSIO G2V1Z DNpPP JNHTR nVTBE CIZTV RXQ6O Z1NIP SP718 2PDXV FQVAR XEVRO VDVX4 XNEWU FGISS nCFQN FVIAU OVYQV P60LK X1ZO2 MXOSZ IV2IV CZVoW YGWZo WYNST GWZBZ 3lZPG IUZXw GWZ2K OYOCX K1BEC KSP0L KU0QG 2VERV YRZFX 0ZFBQ VFSNO CVAn9 VRPQM IXXZC OTNAS QTACO L1QFN PNAOC SCZVC TOYTD 0LKVZ MTAnT CO126 mI0Ap VoWYD 2Z2VI AVCTX 4QVW0 ML91P TACPN AZCVW OBNFQ QJBT2 JHIRS EVXSO AZmQ9 XWYO2 1SCIT WTOLI 1mJIT dVP7T WXnQR PIHDN EWGWZ VcZ2S 1QTXN TSTPS CVAAr XTVp0 LKU0P XWQH2 TSQNX WQXSO SCPHI SQVFW BS5WT CNAPB XNpCR PQW0G VESAC VZ2BG WZCPU REVMO 2FWNT 6ORBT CROCR EVODP LVNEW QPAP7 CA0TS CP82P DXV0I mlANX SOKoZ nAUON 7WXCY FlZXw VX4T5 WC9TA rXTVp TVNSC PLA0I OYAGW wXZAX r7XZo NUPI6 YZRCS P2FZK OCISC NTSVI FUOSL 1C82P 0IWCN SNOCm ATGIS SCnEV PQFV1 w2TAC PNAPI 7Z6AZ k2SCG GOCG0 BX2VC ZlLZE VZMWX nYB2B XNIWA NAHDY XN?IC oN1P9 A0TGI HnWX7 1IZmI GDFGW ZW5T0 9PXHO IAoUN OnSNI LUQVW SQ1LC 2nUNI FXNUn YQTEW N0LKY JMOXW NTnJS 2nTVE CBpVA GISwX ZTSEY QAUOS ZD1KO CPOSQ FNCVI OFVLC AGWZ0 QVIYE D2ICL oCARV P0QBX ZrAKC PHQA0 1TACD AXrFO AVIqI XFPNA OCSCZ VCTOA NlRZY =NCTN nV4XW XCVAC VIqWF JVRTC TO5TX SNOXN EWPYD NAW9N IFXTW 6GWZ4 NTm0Z 4VXET OSRTw XZ6WT NCPSQ NQ9XV ERPNA YAU6P CLZEX ZCTdV P7TUn NPXWI SCNTS TYHNF QCTOI WA7XZ AEPOQ R0PVT X4JCY 01TSN CEXTV XH6WT TQ7nB WISGC WXCRN GWZYJ MCJX7 XZnUT CNoG2 VTWER ETLAI BCX5W TQZOQ YVEWN TO6Ww AKOCX RTCNA SWB5T X2HVw AY2ZB KHEBS VLCAJ CYTW5 VX4XR TNXUI SGCWX 1P8YW LTYNG YDBXN CXFWX nWZFV ApOAU pVACI UYTXY 1BXWn bZVTZ CPNAO SNWwC nVTIW ACJXT 0FZCQ AQSLA ITJ2I W0OIY R9VO6 NCWXO VFWOX QZOFI U2GVC WFDYX X01TZ CAITN OSILU WEBAC IUXNP QRPZJ GWZSN PICNO C}XNU WTCYJ CVX4O SISCP Q9XVE RPNAZ CVBSW AVCFE HAUOC ITCPS 0QUJP VIX6T NEKCP YZR4X VI0SH 2VKOC HQT0P VX1ZZ bVBXP 7WAHT YLCAG WZSRU 0TV0C BFOAA KoGIA ISYTW 6BECG WZXRV PT7IO YUAnK OCKOC XO9CN =XWQX SOSCP TW5ZP UCPUI 1SSQN T0WTI LOIYV Q1oWY PWNCJ XVIq9 NACIT TCSTQ BREVP EASCP GWZoW YNST8 2PWEN CREQJ BpJ0T 6CY0O QTXTX RDARX WOXW6 GWZ9E QSIOD TSFVQ HISLI oNV7G XBXkO TAmCO TCZVQ ZSXSO DYCHT YNXUO UAAoZ HISQV FSPTS CIXZC IWA7X ZIRGN ACXHO QJBT1 0VRXC RNSQN C0NTR E4NTN IKSGT 0LKAY ~7TCW 5TK0T RTX7X ZBMXW 5TREC ZGWQX WQFNP NA0PV CXFmX WFOAA KoGIA ISYTW 6JTFX wAwXZ TPLCI TGNYT 0F0ML <I0TC IQFVJ U1EHF SOPIY EEMAX W6GWZ 2HVXR TECXV IFUOS L1C9X QVFQE XCOVD SNOXN EMAE< I0TCI KoZUA N5IZF X0GWZ SNOIC TZD21 2VOVF TD6qV IFQVn TVO6N lANCB EODT5 WTwAY ZGWQV FIADS BXPNA APVIS YEBNL EZ7WA AROPN A21UN V70Pm IYEPL UUONI SYNSQ ZYrDN VYJCV CSVIq TICPN AYAUT Vp6OV CoNGW ZYJMC JX7XZ FOVEC WT0pW 5TREC CITI1 SnUCI FXNUn W6XOX SpYWO PIV4X CITNO CCNmV nTCPU TCODY HPXWI SC21U mXWVA CVIqQ TXTPL IA[RU SGWZo WYNST VXHSE VIk2m I0PUN ANCVO 6CJXT YHTNA CTOJI mXWoC NUVIF mZJA0 T7COY 1VSQN NEBOI YRTXT D6HTY LCAGW ZYJMC JX7XZ FOVEC WAKoY WoAOY CEYX6 WWBSX HOFwA m0PNO 6TCOU CI6WT URBHV MTXRS PTCN> ABaSI ODTSG OCWOB 1ZCCL BCoNQ JBMZX NPLCF HCUPP RQYQV YAUUA OUPpI FXDTU ONSMO 212SV YQIWA 7ZATB XQFVA 6FRXW lZPQA SAVC1 AY " text=text.replace(" ","") print(encrypt(text,grid))P.S. I believe that P³ is potentially hill-climbable, I have successfully hill climbed it a few times before though it seemed very unreliable.
13th February 2026 at 10:15 am #115359Robb27Participant@madness
Reading your message gave me hope. I have been struggling to write a python program to solve @Puzzling_Pelican’s last cipher. I was able to use THECATSATANDATETHERAT hint to quickly create a program, but building that out to a full solution is proving difficult, and I think relates to the inconsistencies you have found.Finding a rule set, simple or otherwise, to form the encode/decode triangle pairs, has been taxing. I re-started quite a few times. I am coming to the conclusion that it might be better to create a pre-calculated list of all possible encode triangles, and then pre-calculate a matched decode triangle for each. I can then work out which triangle pairs cause problems and try a different orientation for that pairing. Some triangles can have a few possible pairings.
Just as an example: I can define a rule for a simple equilateral triangle, which ‘should’ just need a rotation as shown in the hints. However. a single unit sided triangle will not rotate to a decode pair, the decode would need to be offset somehow or bigger than the encode triangle. A double unit sided triangle might rotate depending on it’s orientation in the hexagon grid or might not.
I won’t be beaten, but I might not solve it until the next NCC starts !!
13th February 2026 at 4:53 pm #115363Robb27Participant@Puzzling_Pelican
Thank-you, I wasn’t expecting to see your upload your code. Your round_midpoint function helped me figure out the second triangle adjustment. I don’t think I would have got there without it even though I had most of the other elements in place. I didn’t use a spiral grid creation routine, just a straight list of the 91 points which I could fill programmatically with a generated key, but I had a very similar grid referencing. With the midpoint adjustment and a few tweaks my code now drops out the correct solution.Just for interest, I will look at brute-forcing this. My quadram scoring works with letters (obviusly), and you divide ‘illegal’ letters with 0 & 1 – easy enough to replace. However, I need to think whether I score decoded texts with lots of the other non-alphabet characters used, or just skip over them. Even just a small key change from the correct solution could mean lots of non-alapha characters, and a brute-force could fail to zero in on a solution if I skip too much. Just ignoring the non-alphabet characters can cause the scoring to go way too low. My quadram routine gives the correct text a score of -17458. I have had much lower scores when ignoring non-alpha characters.
Unlike Playfair, it is not just double letters ‘LL’, ‘OO’ etc to worry about. I had figured ‘THELIGHTHOUSE’ would be a good crib, and was (slowly) some way down a hand decryption. In the trigrams THE-LIG-HTH-OUS the combination ‘HTH’ would clearly not make a triangle, so I could see that additional plain text padding would be required.
Thanks again for an interesting final cipher puzzle.
14th February 2026 at 8:39 am #115368_madness_Participant@Puzzling_Pelican
Here are some examples where my choices come closer to the cipher that you describe. Trigrams may be in the wrong order, but that is irrelevant.
your ciphertext: JIm
your plaintext: LEB
my pairing to JIm: vFWyour ciphertext: RCE
your plaintext: EVR
my pairing to RCE: XN4your ct: PUC
your pt: PSU
my pt: 1ONyour ct: CUn
your pt: OFD
my pt: RXByour ct: cZV
your pt: MRF
my pt: a5XAnd then there are some that are ambiguous, and a standard needs to be set. Here are examples:
0QU matches M6C or LSA
Q7T matches RVI or 5PU
PST matches QIN or RCU
NZp matches OWG or PXr
0VE matches PZB or HIDI’m glad I cheated. Ha ah aha ha ha ha.
22nd February 2026 at 8:36 pm #115382Puzzling_PelicanParticipant@madness
Apologies for the long wait.
All the examples you provided originate from the same root cause, the midpoint being perfectly in the middle of 3 corners of the grid.
My original code has a bug where it would fail to detect this case correctly and so would produce different results to what you expected.
I have now fixed this and it seems to be far closer to the examples you provided.At the moment, the rule for this case is to round the y coordinate vertically and it seems to works nicely most of the time and is always consistent and self inverse. If you have a better suggestion, I would love to hear it. Having to add this rule was my biggest regret with the design of this cipher (except failing to implement the rule correctly in Python).
To fix the code from my previous post, replace
# The original code written for this case was broken so the original 10B encrypt ignored this and treated it the same as the axis case.with
if (_is_whole_num(x) or _is_whole_num(x - 0.5)) and (_is_whole_num(y - 1/3) or _is_whole_num(y + 1/3)): y = round(y) return (x, y)This creates a slightly different ciphertext:
ATDCR OCNUw 10Pm0 5WT1M AQXUC VAArX 7CPpS P12VP GBGTS OTE2X UYSAH PTSQN I0TWN EPNA0 PWI0T NREW6 A2VIA OUO2M XOSXW OpPSU EQXHO GWZYJ MCJX7 XZT5W 1YWNE WPZBN EWHSC FTVOC R9VnA UCCXN AUOAU NSCPG YDDFT UI1SI FHUaO VDVX4 TSWGF TNEWH SCKQP GOCY1 9X2VZ WFWUE CNTTS nWXnA KFWoJ TVnX0 15WTF OAAKo qZYIS YTW6P OSQFN PNANT S7XZX ErZWF XNWZW LA6FC WXORA OTESW ETD6H TYSVC Z2SDT 67QNS OP2GV MEIUC A9RV6 QNWXn T0FAS PTSEH FCCIT YZSRI NPYBR NEWXC wTXZA mMYTR ENNAH TYNVX 4PUTP C7EWN XCSXK PFQNL CAGWZ ZAHAO DWPXW XnpNI GWZGI SLEYA Xr7XZ GPBON SB2ZX CNJPN LQNYW MW5TQ NFHCZ ECBHI RWZTN PLAOU CZ9PN A9SVO SAWNG 1MLT2 JV4XC ITTCS n0ZWN EISCA XRR9V AUCZ1 DYJMO XWQXW QFNPN ANTSP JUDEn YJCQP AP7TX HOESW AUODY CQWVZ lQNST WYOIT LXSOX HOTWE RET2N JQWXA UOPIR OFVY1 B0ImD YCASP CYGPN AW9CE LYEWN 1MLYJ MOXWS XWOSn GWZSH WXRW0 AGCRN IRQPV JBENA HTMAE 0C1XT ASCPA T5GWZ UX3SI ODTSY RCP0N CTOCS DTSnA OSnWX GWZ2K RTWOm I0VAp WONNP SUPGP ZBPpN lPZaV Z6WAT 4NrV2 12SRP QW0GV ESACV Z2BFO VJN3A OSPLo CPSRN TXHOI PAT0W TILVQ Y1ZNG WZNTC O5NAV NSCPF OAVIG TXnMO 2ANUP NA0PV WYOT6 C6VOV NAX4N 1ZCCL BCoNR PQVRX AUCSZ FO}CR XWOWY Z1DYJ MOXW4 VXCYD UONX1 JSROm ATnSO ATULC AICTW 9CD1Z EHFVX HTmAN EWY1X mTAXC INREC AUAWQ NOSLO CZ2BP JNHTR ZD2NS TOWYN AT0LA OXSCA SAITS ROBEC XWQXS OSCPA DLVFQ AITTS EHTYL TI0U1 AKoqZ YISYT W6PCE C1LIL TNAFR 9VASC JWFD9 WT9pC OTOXS ECXWZ pCZYA XR21N WP0ZF BUNAn TVIOR ROSQN 6DTST RNV4X CITSR OA0TS IOELZ GISYH TPHNG OCY19 X2V4A VW5TO XWCAD JCYSU OOQ6U PpPXT LOC1I UFYSS nCOTE VaHWX CAXmI SYN7V XOHY1 XCIPO RTPKS GWZRI QPT7C ISXVA 1JYQT X0MLD 2ZTlX ELYRS NPBXC GOQRI QMUAO SXWOO RSQNT NTSUO IVSET 1WX4N LCAIS GCWX1 ZNGWZ VACPS pXZCF OAAKo qZYIS YTW6B ECYBT WETCA UBVOP 16ENS 82PAT XnXWO SIDYC EIJZI NTCOC TZGWZ PCEUN OFQNn TVUVN ERNTY HGWZU 0ZZmI GDFGW ZZAHF TDSVP VFQwT XCnNO RSQNA ICQTF GCZlP NFDNV TYHTN AANDT CO126 mI0ZA nTAoC VIMAE mP1TC ILEIG WZSNP ICNOC }AONS ROmAT 03N09 PROIF YSTAn TCOCT ZD2ZP ZUOXS pYW10 XXMZB 2HBEC JoTTI CVHaR OCOE9 LPIVR XnUNY BEWZF VApPZ UZ6AZ k2TUn SBXnS OBECG DYFQN 0PIRP QOIRW XCZbV DTSCU =PU1C NAQUE 3TVQF NPNA0 PVHCZ LOCZ2 BASCS CFTXP AT5GW ZOZQA ITIVC SXAVA CRET1 T0LCQ 91PCI PPNAL OCENW 4NTRv CNV7A NDNFQ QJBVQ J6NQw NTEBW SWEPT 7YSAT YHRSN QYVOX 9DLAA TXPM7 JWoAC NLCAG WZCSN WQXAG WQVFQ 9XNTP QFV4A V5WTI 1SZ2B IUFF0 1VXHP WYBCX RENNE WpJ0X kONCn ASPQB JOXWW XnWZF VAp31 UNV7E BWSIO G2V1Z DNpPP JNHTR nVTBE CIZTV RXQ6O Z1NZI NP718 2PDXV FQVAR XXN4O VDVX4 TSWWU FGISS nCFQN pWZAU OVYQW IS1ML AM0O2 MXOSZ IV2IV P0NFT ZGWZF TZNST GWZBZ 3lZPG IUYEL GWZ2K OYOCE JIBEC KSP1M LVJPG 2VX4N FSYFX 0ZFBQ VFNTC CVAn9 VRPQM IXXZC OTNAS QCIPO L1QFN PNAOC SP0NC TOYTD 1MLVZ MTAnT CO126 mI0Ap VFTZD 2Z2VI AVCTX 4QVW0 ML91P CIPPN A0PNW OBNFQ QJBT2 JHIRS EVXSO AZmQ9 XWYO2 1SCIT WTOLI 1l0PX 4WP7T WXnQR PPZBN EWGWZ W3H2S 1QTXN TSNQ6 CVAAr XTVp1 MLU0P XWQH2 TSQNX WQXSO SCPGA UQVFW BS5WT CNAPB XT?AR PQW0G VESAC VZ2BG WZOQ7 4XNMO 2XVSX SCRBT CROTS nVODQ MUNEW QPAP7 CA0TS CP82P DXV0I mmYTX SOLEI nAUON 7WXCY FlYEL VX4T5 WPUCA rXTVp CNOSC PLA0A NFAGW LEYAX r7XZ> TVPI6 FYSCS PaY0K OCISC NTSWZ pUOSL 1C82P 0IWCN SSROm ATGIS SCnEV PQFV1 w2CIP PNAPI 7Z6AZ k2RPH GOCY1 9X2VC ZlLZE VZMWX nZVaD FTIWA NAHDY XSpPC oN1P9 A0TYP ZnWXU 0ZZmI GDFGW ZW5T0 9PXHO PCEUN OnSNP M7QVW R3MLC 2nUNP XTNUn YQTEW N1MLY JMOXW NTnJS 2nTVE CBpVA GISLE YTSEF OXUOS ZD1KO CPOSQ FNCVI OFVLC AGWZ0 QVPAW D2ICL oCARV P0QBX IHCKC PHQA0 1TACD AXrFO AUPGP TXPNA OCSP0 NCTOY TmSYF nSOTN nV4XW XCVAC UPGWF JVRTC TO5TX NTCTS WWPYD NAW9N PXTTW 6GWZ4 NTl1I 4VXET ONOXL EY6WT NCPSQ NQ9XN X4PNA YAU6P CLZEX ZCX4W P7TUn NPXWI SCNTS TYHNF QCTOI WA7XZ AEPNO S0PVT X4JCY 01TSN CEXTV XH6WT XPUnB WISGC WXCRN GWZYJ MCJX7 XZnUT CNoG2 VTWER ETLAI BCX5W TQZOQ YVEWN XCSWw AKOCE SWCNA SWB5T XPGBL XF2ZB LZWBS VLCAJ CYTW5 VX4ES WOASI SGCWX 1P8YW LTYNG YDDFT CXFWX nWZFV ApOAU pVACI UYTXY 1BXWn bZVTZ CPNAC NTWwC nVTIW ACJXT 0FIO4 AQSLA ITJ2I W0NAF R9VO6 NCWXO VFWOX QZOFI U2GVC WFDYX X01TZ CAITT CNPM7 WEBXT ASAOP QRCYH GWZSN PICNO C}AOS WTCYJ CVX4O SISCP Q9XNX 4PNA0 PNBSW AVCFE HAUOC ITCPS JPVHC BIX6T NEKCP FYS4X VP16G PBKOC GOW0P VAM0Z bVBXP 6TIHT YLCAG WZSRU LCNLP VFOAA KoqZY ISYTW 6BECG WZXRV PT7AN FUAnK OCKOC AQUOS nXWQX SOSCP TW5ZP UOQ7I 1SSQN T0WTI LNAFW P0FTZ CDVCJ XUPGU OICIT TCSTQ B4XNP EASCP GWZFT ZNST8 2PWEN TSnQJ BpJ0T 6CY0O QTXWE SDARX WOAT5 GWZUX 3SIOD TSFVQ GAULI oNV7G XBXkO TAmCO TP0NP HNXSO DYCHT YOASO UAAoZ GAUQV F6QNS CIXZC IWA7X ZASpN ACXHO QJBT1 0VRXC RNSQN C0NTR E4NTN IKSGT 1MLAY ~7TCW 5TJZW SWE7X ZVxAW 5TSnT ZGWQX WQFNP NA0PV CXFDA TFOAA KoqZY ISYTW 6JTFX wALEY TPLCI TYSAT 0F0ML mP1TC IQFVJ U1EHF SOPPA WEMAA T5GWZ PGBES WECXW ZpUOS L1C9X QVFQE XCOVD NTCTS WMAEm P1TCI LEIUA N5IZF X0GWZ NTCIC TZD21 2VOVF TD6GU PFQVn TVO6N mYTCB EODT5 WTLXF ZGWQV FZYnS BXPNA APVIS YEBNL EZ6TI AROPN A21UN V70Pm PAWPL UUONI SYNSQ ZYrDN VYJCV CSUPG TICPN AYAUT Vp6OV CoNGW ZYJMC JX7XZ FOVWO VT0pW 5TSnT CITI1 S=VAP XTNUn T5AOX SpYWO PIV4X CITSR OAT<V nTOQ7 TCOmF GPXWI SC21U DATVA CUPGQ TXTPL PCrRU SGWZF TZNST VXHSE VIk2m I0PUN ANCVO 6CJXT YHTNA CTO0P lXWoC NUWZp mZJA0 TUACY 1VSQN NEBNA FSWET D6HTY LCAGW ZYJMC JX7XZ FOVWO VAKoZ TFAOY CEYA5 TWBSX HOFwA m0PNO 6TCOU CI6WT URBHV MWES6 QNCN> ABaSI ODTSG OCWOB 1ZCCL BCoNQ JBMZX NPLCF HO7QP RQYQV YAUUA OUPpP XTDTU CTNMO 212SV YQIWA 7ZATB XQFVA 6FRXW lZPQA SAVCM IZI hope this clears up the confusion caused by this bug. Please let me know if your solution now matches or if there are still inconsistencies we need to figure out.
Thank you for helping work out what was broken,
Daniel23rd February 2026 at 6:06 pm #115370Puzzling_PelicanParticipant@madness thanks for these examples, from the looks of things, almost all of them are caused by the exact same bug in the code which caused 1x1s to be broken. When the midpoint is perfectly in the middle of 3 letters, some consistent rounding needs to be performed on it. Originally this was to move it vertically to the nearest valid midpoint however my code did not perform this correctly and so ended up rounding diagonally (which is also why 1×1 mappings form alternating diagonals). It turns out that this one bug caused more issues than I thought. I will try to fix it in a bit unless you fix it first.
As for the inconsistent ones you have picked, I can only understand how one of the two are valid, from what I see performing the cipher manually, the midpoint is already considered ‘valid’ and so is not rounded before points are reflected in it.
Finally, if you have a better idea for what happens in the case that the midpoint is perfectly in the middle of 3 letters, other than a vertical move (or whatever the bug in my code did to it), I would love to hear it. This was one of the biggest compromises I made in the ruleset for P3. Only requirements are that it is consistent, simple and self inverse (same to encryption and decrypt).
Thanks again,
Daniel -
AuthorPosts
- You must be logged in to reply to this topic.