// The Troublesome Gospel of St. Clinton // This program finds reverse translation of Clint Williams' lossy numerical // encoding of the Bible: // // http://www.c-c-w.net/numerical/ // dict is a dictionary of words, keyed by their numeric values, values // are an array of words that this number maps to. dict = new dict // Effectively, this is a "set" of the words we've seen. // TODO: need to implement efficient sets. usedDict = new dict // Paths to several Moby wordlists (not included) // The wordlist files are part of the Moby wordlist project, available at: // http://icon.shef.ac.uk/Moby/ files = ["file:///home/eliasen/prog/mobydict/mwords/singlewords.txt", "file:///home/eliasen/prog/mobydict/mwords/compoundwords.txt", "file:///home/eliasen/prog/mobydict/mwords/names.txt", "file:///home/eliasen/prog/mobydict/mwords/places.txt"] // Load in the wordfiles and convert words to their numeric values for file = files numeric[read[file], usedDict, dict] // Read in wordlists usedDict = undef // Now perform dechiffrage orig = read["http://www.c-c-w.net/numerical/"] orig =~ %s/<[^>]*>/ /gs // Strip HTML orig =~ %s/[^0-9]+/ /gs // Strip all non-numbers & condense spaces decipher[orig, dict] // Function to turn a text into its string representations // and insert each word mapping into a dictionary. // numeric[string, usedDict, dict] := { words = split[%r/\s+/s, string] // Split into words for word = words { if word =~ %r/[^A-Za-z]/ // Discard non-alphabetic words. next if word =~ %r/[A-Z]{2,}/ // Two or more uppercase letters? Skip 'em. next capWord = uppercase[word] // Make all keys uppercase if (usedDict@capWord) // Already seen it? next usedDict@capWord = true // Mark word as used // Make numeric value. This could be done more concisely if we // had a map[] function. ret = "" for char = chars[capWord] { char = char - char["A"] + 1 ret = ret + "$char" } // See if number exists already if (dict@ret != undef) { dict@ret.push[word] // Already exists // println[dict@ret] // Comment in to see hash collisions } else dict@ret = [word] // Doesn't exist, create a one-element array } } // Function to decipher a string of text, using a dictionary that // was already built decipher[string, dict] := { words = split[%r/\s+/s, string] // Split on spaces for num = words { rev = dict@num if (! rev) print["$num "] // Word not found, print numeric value else if (length[rev] == 1) print[rev@0 + " "] // Only one word; print without brackets else print["$rev "] // More than one mapping, print array } }