Created
January 17, 2023 21:03
-
-
Save marnanel/90f256b17b8cd4a98724ede9a95ca6b8 to your computer and use it in GitHub Desktop.
Analysis of Kryptos panels
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from PIL import Image, ImageDraw | |
| # non-Python people should note that this is valid JSON | |
| PANELS = { | |
| "A000": "BETWEENSUBTLESHADINGANDTHEABSENC", | |
| "A001": "EOFLIGHTLIESTHENUANCEOFIQLUSION", | |
| "A002": "ITWASTOTALLYINVISIBLEHOWSTHATPO", | |
| "A003": "SSIBLE?THEYUSEDTHEEARTHSMAGNET", | |
| "A004": "ICFIELDXTHEINFORMATIONWASGATHER", | |
| "A005": "EDANDTRANSMITTEDUNDERGRUUNDTOANU", | |
| "A006": "NKNOWNLOCATIONXDOESLANGLEYKNOWA", | |
| "A007": "BOUTTHIS?THEYSHOULDITSBURIEDOUT", | |
| "A008": "THERESOMEWHEREXWHOKNOWSTHEEXACTL", | |
| "A009": "OCATION?ONLYWWTHISWASHISLASTMES", | |
| "A010": "SAGEXTHIRTYEIGHTDEGREESFIFTYSE", | |
| "A011": "VENMINUTESSIXPOINTFIVESECONDSNO", | |
| "A012": "RTHSEVENTYSEVENDEGREESEIGHTMINU", | |
| "A013": "TESFORTYFOURSECONDSWESTXLAYERTW", | |
| "A100": "SLOWLYDESPARATLYSLOWLYTHEREMAINS", | |
| "A101": "OFPASSAGEDEBRISTHATENCUMBEREDT", | |
| "A102": "HELOWERPARTOFTHEDOORWAYWASREMOV", | |
| "A103": "EDWITHTREMBLINGHANDSIMADEATINY", | |
| "A104": "BREACHINTHEUPPERLEFTHANDCORNERAN", | |
| "A105": "DTHENWIDENINGTHEHOLEALITTLEIIN", | |
| "A106": "SERTEDTHECANDLEANDPEEREDINTHEHOT", | |
| "A107": "AIRESCAPINGFROMTHECHAMBERCAUSED", | |
| "A108": "THEFLAMETOFLICKERBUTPRESENTLYDETA", | |
| "A109": "ILSOFTHEROOMWITHINEMERGEDFROM", | |
| "A110": "THEMISTXCANYOUSEEANYTHINGQ?", | |
| "A111": "", | |
| "A112": "", | |
| "A113": "", | |
| "Q000": "EMUFPHZLRFAXYUSDJKZLDKRNSHGNFIVJ", | |
| "Q001": "YQTQUXQBQVYUVLLTREVJYQTMKYRDMFD", | |
| "Q002": "VFPJUDEEHZWETZYVGWHKKQETGFQJNCE", | |
| "Q003": "GGWHKK?DQMCPFQZDQMMIAGPFXHQRLG", | |
| "Q004": "TIMVMZJANQLVKQEDAGDVFRPJUNGEUNA", | |
| "Q005": "QZGZLECGYUXUEENJTBJLBQCRTBJDFHRR", | |
| "Q006": "YIZETKZEMVDUFKSJHKFWHKUWQLSZFTI", | |
| "Q007": "HHDDDUVH?DWKBFUFPWNTDFIYCUQZERE", | |
| "Q008": "EVLDKFEZMOQQJLTTUGSYQPFEUNLAVIDX", | |
| "Q009": "FLGGTEZ?FKZBSFDQVGOGIPUFXHHDRKF", | |
| "Q010": "FHQNTGPUAECNUVPDJMQCLQUMUNEDFQ", | |
| "Q011": "ELZZVRRGKFFVOEEXBDMVPNFQXEZLGRE", | |
| "Q012": "DNQFMPNZGLFLPMRJQYALMGNUVPDXVKP", | |
| "Q013": "DQUMEBEDMHDAFMJGZNUPLGEWJLLAETG", | |
| "Q100": ".ABCDEFGHIJKLMNOPQRSTUVWXYZABCD", | |
| "Q101": "AKRYPTOSABCDEFGHIJLMNQUVWXZKRYP", | |
| "Q102": "BRYPTOSABCDEFGHIJLMNQUVWXZKRYPT", | |
| "Q103": "CYPTOSABCDEFGHIJLMNQUVWXZKRYPTO", | |
| "Q104": "DPTOSABCDEFGHIJLMNQUVWXZKRYPTOS", | |
| "Q105": "ETOSABCDEFGHIJLMNQUVWXZKRYPTOSA", | |
| "Q106": "FOSABCDEFGHIJLMNQUVWXZKRYPTOSAB", | |
| "Q107": "GSABCDEFGHIJLMNQUVWXZKRYPTOSABC", | |
| "Q108": "HABCDEFGHIJLMNQUVWXZKRYPTOSABCD", | |
| "Q109": "IBCDEFGHIJLMNQUVWXZKRYPTOSABCDE", | |
| "Q110": "JCDEFGHIJLMNQUVWXZKRYPTOSABCDEF", | |
| "Q111": "KDEFGHIJLMNQUVWXZKRYPTOSABCDEFG", | |
| "Q112": "LEFGHIJLMNQUVWXZKRYPTOSABCDEFGH", | |
| "Q113": "MFGHIJLMNQUVWXZKRYPTOSABCDEFGHI", | |
| "Q200": "ENDYAHROHNLSRHEOCPTEOIBIDYSHNAIA", | |
| "Q201": "CHTNREYULDSLLSLLNOHSNOSMRWXMNE", | |
| "Q202": "TPRNGATIHNRARPESLNNELEBLPIIACAE", | |
| "Q203": "WMTWNDITEENRAHCTENEUDRETNHAEOE", | |
| "Q204": "TFOLSEDTIWENHAEIOYTEYQHEENCTAYCR", | |
| "Q205": "EIFTBRSPAMHHEWENATAMATEGYEERLB", | |
| "Q206": "TEEFOASFIOTUETUAEOTOARMAEERTNRTI", | |
| "Q207": "BSEDDNIAAHTTMSTEWPIEROAGRIEWFEB", | |
| "Q208": "AECTDDHILCEIHSITEGOEAOSDDRYDLORIT", | |
| "Q209": "RKLMLEHAGTDHARDPNEOHMGFMFEUHE", | |
| "Q210": "ECDMRIPFEIMEHNLSSTTRTVDOHW?OBKR", | |
| "Q211": "UOXOGHULBSOLIFBBWFLRVQQPRNGKSSO", | |
| "Q212": "TWTQSJQSSEKZZWATJKLUDIAWINFBNYP", | |
| "Q213": "VTTMZFPKWGDKZXTJCDIGKUHUAUEKCAR", | |
| "Q300": "NGHIJLMNQUVWXZKRYPTOSABCDEFGHIJ", | |
| "Q301": "OHIJLMNQUVWXZKRYPTOSABCDEFGHIJL", | |
| "Q302": "PIJLMNQUVWXZKRYPTOSABCDEFGHIJLM", | |
| "Q303": "QJLMNQUVWXZKRYPTOSABCDEFGHIJLMN", | |
| "Q304": "RLMNQUVWXZKRYPTOSABCDEFGHIJLMNQ", | |
| "Q305": "SMNQUVWXZKRYPTOSABCDEFGHIJLMNQU", | |
| "Q306": "TNQUVWXZKRYPTOSABCDEFGHIJLMNQUV", | |
| "Q307": "UQUVWXZKRYPTOSABCDEFGHIJLMNQUVW", | |
| "Q308": "VUVWXZKRYPTOSABCDEFGHIJLMNQUVWX", | |
| "Q309": "WVWXZKRYPTOSABCDEFGHIJLMNQUVWXZ", | |
| "Q310": "XWXZKRYPTOSABCDEFGHIJLMNQUVWXZK", | |
| "Q311": "YXZKRYPTOSABCDEFGHIJLMNQUVWXZKR", | |
| "Q312": "ZZKRYPTOSABCDEFGHIJLMNQUVWXZKRY", | |
| "Q313": ".ABCDEFGHIJKLMNOPQRSTUVWXYZABCD" | |
| } | |
| FORWARDS = [ | |
| ('B', 'N', '#ff0000'), | |
| ('E', 'Y', '#ff7700'), | |
| ('R', 'P', '#ffff00'), | |
| ('L', 'V', '#00ff00'), | |
| ('I', 'T', '#0000ff'), | |
| ('N', 'T', '#7777ff'), | |
| ] | |
| BACKWARDS = [ | |
| ('N', 'B', '#ff0000'), | |
| ('Y', 'E', '#ff7700'), | |
| ('P', 'R', '#ffff00'), | |
| ('V', 'L', '#00ff00'), | |
| ('T', 'I', '#0000ff'), | |
| ('T', 'N', '#7777ff'), | |
| ] | |
| def main(goals, output_filename): | |
| pivoted_panels = {} | |
| for plane in ('Q0', 'Q1', 'Q2', 'Q3', 'A0', 'A1'): | |
| for i in range(40): | |
| key = 'p%s%02d' % (plane, i) | |
| pivoted_panels[key] = '' | |
| for j in sorted(PANELS.keys()): | |
| if not j.startswith(plane): | |
| continue | |
| try: | |
| pivoted_panels[key] += PANELS[j][i] | |
| except: | |
| pass | |
| def burial_lookup(naming, buried, letter): | |
| result = set() | |
| for i in range(min(len(naming), len(buried))): | |
| if naming[i]==letter: | |
| result.add(buried[i]) | |
| return result | |
| panel_keys = sorted(PANELS.keys()) | |
| pivoted_keys = sorted(pivoted_panels.keys()) | |
| im = Image.new("RGB", (len(pivoted_keys)*8+10, len(pivoted_keys)*8+10), color="#ffffff") | |
| draw = ImageDraw.Draw(im, "RGBA") | |
| for naming_i in range(len(pivoted_keys)): | |
| for buried_i in range(len(pivoted_keys)): | |
| naming = pivoted_panels[pivoted_keys[naming_i]] | |
| buried = pivoted_panels[pivoted_keys[buried_i]] | |
| x = 5 + naming_i * 8 | |
| y = 5 + buried_i * 8 | |
| colours = [] | |
| for (source, target, then_colour) in goals: | |
| if target in burial_lookup(naming, buried, source): | |
| colours.append(then_colour) | |
| if len(colours)==0: | |
| draw.rectangle(((x,y), (x+5,y+5)), fill='#bbbbbb') | |
| else: | |
| ALLOCATION = [ | |
| [], | |
| [0,0,0,0,0,0], | |
| [0,0,0,1,1,1], | |
| [0,0,1,1,2,2], | |
| [0,0,1,2,2,3], | |
| [0,1,1,2,3,4], | |
| [0,1,2,3,4,5], | |
| ] | |
| allocation = ALLOCATION[len(colours)] | |
| for c in range(5): | |
| draw.rectangle(((x,y+c), (x+5,y+c)), | |
| fill=colours[allocation[c]]) | |
| im.save(open(output_filename, 'wb'), 'PNG') | |
| if __name__=='__main__': | |
| main(FORWARDS, 'forwards.png') | |
| main(BACKWARDS, 'backwards.png') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment