Skip to content

Instantly share code, notes, and snippets.

@stsquad
Created March 26, 2018 10:53
Show Gist options
  • Save stsquad/665542a64e99b71a4ef128aad4f00ab1 to your computer and use it in GitHub Desktop.
Save stsquad/665542a64e99b71a4ef128aad4f00ab1 to your computer and use it in GitHub Desktop.

Solving the HKG18 puzzle with org-mode

One of the traditions I like about Linaro’s Connect event is the conference puzzle. Usually set by Dave Piggot they provide a challenge to your jet lagged brain. Full disclosure: I did not complete the puzzle in time. In fact when Dave explained it I realised the answer had been staring me in the face. However I thought a successful walk through would make for a more entertaining read ;-)

First the Puzzle:

Take the clues below and solve them. Once solved, figure out what the hex numbers mean and then you should be able to associate each of the clue solutions with their respective hex numbers.

ClueHex Number
Lava Ale Code1114DBA
Be Google Roe114F6BE
Natural Gin114F72A
Pope Charger121EE50
Dolt And Hunk12264BC
Monk Hops Net122D9D9
Is Enriched Tin123C1EF
Bran Hearing Kin1245D6E
Enter Slim Beer127B78E
Herbal Cabbages1282FDD
Jan Venom Hon Nun12853C5
A Cherry Skull1287B3C
Each Noun Lands1298F0B
Wave Zone Kits12A024C
Avid Null Sorts12A5190
Handcars All Trim12C76DC

Clues

It looks like all the clues are anagrams. I was lazy and just used the first online anagram solver that Google pointed me at. However we can automate this by combining org-mode with Python and the excellent Beautiful Soup library.

from bs4 import BeautifulSoup
import requests
import re

# ask internet to solve the puzzle
url="http://anagram-solver.net/%s" % (anagram.replace(" ", "%20"))
page=requests.get(url)

# fish out the answers
soup=BeautifulSoup(page.text)
answers=soup.find("ul", class_="answers")
for li in answers.find_all("li"):
    result = li.text
    # filter out non computer related or poor results
    if result in ["Elmer Berstein", "Tim-Berners Lee", "Babbage Charles", "Calude Shannon"]:
        continue
    # filter out non proper names
    if re.search("[a-z] [A-Z]", result):
        break

return result

So with :var anagram=clues[2,0] we get

Ada Lovelace

I admit the “if result in []” is a bit of hack.

Hex Numbers

The hex numbers could be anything. But lets first start by converting to something else.

Hex PromptNumber
1114DBA17911226
114F6BE18151102
114F72A18151210
121EE5019000912
12264BC19031228
122D9D919061209
123C1EF19120623
1245D6E19160430
127B78E19380110
1282FDD19410909
12853C519420101
1287B3C19430204
1298F0B19500811
12A024C19530316
12A519019550608
12C76DC19691228

The #+TBLFM: is $1='(identity remote(clues,@@#$2))::$2='(string-to-number $1 16)

This is where I went down a blind alley. The fact all they all had the top bit set made me think that Dave was giving a hint to the purpose of the hex number in the way many cryptic crosswords do (I know he is a fan of these). However the more obvious answer is that everyone in the list was born in the last millennium.

Looking up Birth Dates

Now I could go through all the names by hand and look up their birth dates but as we are automating things perhaps we can use computers for what they are good at. Unfortunately there isn’t a simple web-api for looking up this stuff. However there is a project called DBpedia which takes Wikipedia’s data and attempts to make it semantically useful. We can query this using a semantic query language called SparQL. If only I could call it from Emacs…

PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>

select ?birthDate where {
  { dbr:$name dbo:birthDate ?birthDate }
  UNION
  { dbr:$name dbp:birthDate ?birthDate }
}

So calling with ~:var name=”Ada_Lovelace”~ we get

"birthDate"
1815-12-10
1815-12-10

Of course it shouldn’t be a surprise this exists. And in what I hope is a growing trend sparql-mode supports org-mode out of the box. The $name in the snippet is expanded from the passed in variables to the function. This makes it a general purpose lookup function we can use for all our names.

There are a couple of wrinkles. We need to format the name we are looking up with underscores to make a valid URL. Also the output spits out a header and possible multiple birth dates. We can solve this with a little wrapper function. It also introduces some rate limiting so we don’t smash DBpedia’s public SPARQL endpoint.

;; rate limit
(sleep-for 1)
;; do the query
(let* ((str (s-replace-all '((" " . "_") ("Von" . "von")) name))
       (ret (eval
             (car
              (read-from-string
               (format "(org-sbe get-dob (name $\"%s\"))" str))))))
  (string-to-number (replace-regexp-in-string "-" "" (car (cdr (s-lines ret))))))

Calling with ~:var name=”Ada Lovelace”~ we get

18151210

Full Solution

So now we know what we are doing we need to solve all the puzzles and lookup the data. Fortunately org-mode’s tables are fully functional spreadsheets except they are not limited to simple transformations. Each formula can be a fully realised bit of elisp, calling other source blocks as needed.

ClueSolutionDOB
Herbal CabbagesCharles Babbage17911226
Be Google RoeGeorge Boole18151102
Lava Ale CodeAda Lovelace18151210
A Cherry SkullHaskell Curry19000912
Jan Venom Hon NunJohn Von Neumann19031228
Pope ChargerGrace Hopper19061209
Natural GinAlan Turing19120623
Each Noun LandsClaude Shannon19160430
Dolt And HunkDonald Knuth19380110
Is Enriched TinDennis Ritchie19410909
Bran Hearing KinBrian Kernighan19420101
Monk Hops NetKen Thompson19430204
Wave Zone KitsSteve Wozniak19500811
Handcars All TrimRichard Stallman19530316
Enter Slim BeerTim Berners-Lee19550608
Avid Null SortsLinus Torvalds19691228

The #+TBLFM: is $1='(identity remote(clues,@@#$1))::$2='(org-sbe solve-anagram (anagram $$1))::$3='(org-sbe frob-dob (name $$2))

The hex numbers are helpfully sorted so as long as we sort the clues table by the looked up date of birth using M-x org-table-sort-lines we are good to go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment