commit 1e3a73ec5ef1d8e5c5c10d6d8b88a18231aeea8b Author: Levi Pearson Date: Thu Jun 28 20:08:11 2018 -0600 Initial commit diff --git a/provided/codex.umz b/provided/codex.umz new file mode 100644 index 0000000..8b60139 Binary files /dev/null and b/provided/codex.umz differ diff --git a/provided/sandmark.umz b/provided/sandmark.umz new file mode 100644 index 0000000..1bb2145 Binary files /dev/null and b/provided/sandmark.umz differ diff --git a/provided/task.html b/provided/task.html new file mode 100644 index 0000000..13b9d0d --- /dev/null +++ b/provided/task.html @@ -0,0 +1,257 @@ + + + +ICFP Programming Contest, 2006 : Contest Materials and Task + + + + + + +
+ +
+
Ninth annual
ICFP Programming Contest
+
Hosted by Carnegie Mellon University's POP Group
+
+ + + + + + + +
+ + + +
+ +

An Urgent Appeal

+ +

+Dear Colleague: +

+ +

+In 1967, during excavation for the construction of a new shopping +center in Monroeville, Pennsylvania, workers uncovered a vault +containing a cache of ancient scrolls. Most were severely damaged, +but those that could be recovered confirmed the existence of a secret +society long suspected to have been active in the region around the +year 200 BC. +

+ +

+Based on a translation of these documents, we now know that the +society, the Cult of the Bound Variable, was devoted to the careful +study of computation, over two millennia before the invention of the +digital computer. +

+ +

+While the Monroeville scrolls make reference to computing machines +made of sandstone, most researchers believed this to be a poetic +metaphor and that the "computers" were in fact the initiates +themselves, carrying out the unimaginably tedious steps of their +computations with reed pens on parchment. A few have conjectured a +city-sized machine powered by falling sand, but no physical evidence +of such a device has been discovered. +

+ +

+Among the documents found intact in the Monroeville collection was a +lengthy codex, written in no known language and inscribed with +superhuman precision. It is believed to be the masterwork of the +Cult's scholarship, and as such it carries immense potential to +advance our understanding of history—and possibly of computing as +well. Unfortunately, the codex eluded interpretation, and over the +decades, study of the Monroeville scrolls has slipped into obscurity. +Since 1978, the codex has been stored in the basement of the Carnegie +Museum of Natural History. +

+ + +

+Two weeks ago, during a visit to the excavation site for a new +computer science building at CMU, workers discovered a set of +inscribed tablets that proved to be the Rosetta Stone for interpreting +the Monroeville codex. The tablets precisely specify the Cult's +computing device, known to initiates as the "Universal Machine." +Although there is still no evidence that the cult succeeded in +constructing their machine, it is a reasonably simple task to emulate +it on modern hardware. +

+ +

+We can now say with certainty that the codex is in fact a program, +intended for execution on the Universal Machine. Our initial +exploration of the codex suggests that the Cult's ideas about +programming were very sophisticated, if somewhat peculiar to the +modern eye. One cannot help but wonder what the Cult might have +achieved had they had access to modern electronics and type theory. +

+ +

+I have enlisted the help of the CMU Principles of Programming group in +creating a venue for study of the codex. We invite you to participate +in this investigation. The codex and a translation of the Universal +Machine (UM) specification are available for download from our web site. We encourage you to +implement the UM and begin your own exploration of the codex. When +you are prompted to enter a decryption key, type the following string: + (\b.bb)(\v.vv)06FHPVboundvarHRAk +

+ +

+The Cult's scholarly publications are of particular interest to us. +Because the Cult's journals were circulated on sandstone tablets, +editors imposed very strict length limitations. Consequently, authors +aggressively compressed their articles. A typical publication would +have the following form: +

+ +
PUZZL.TSK=100@1001|14370747643c6d2db0a40ecb4b0bb65
+ +

+ +Publications are of varying +value; some will represent a greater contribution than others. Given our +understanding of the Cult's publication process, we believe there is a +mechanism within the codex that will verify a set of publications and compute their total +value. + +

+ +

+On a personal note, being inspired by the scholarship of the +Cult, I have decided to dedicate the remainder of my days to a solitary +study of computation and programming languages. However, before +embarking on my monastic transformation, I wish to see that the +world is well on its way to uncovering the secrets of the Codex. +

+ +

+Therefore, I ask that you submit as many publications as you can by +noon EDT on July 24, 2006, at which time I will be taking my orders. +My colleagues in the CMU POP group assure me that at that time, the +teams that have made the greatest contribution to the effort shall be +identified for special recognition. +

+ +

+Good luck and thank you for your assistance. +

+ + +

+Sincerely,
+
+Professor Emeritus Harry Q. Bovik
+Computational Archaeolinguistics Institute
+Carnegie Mellon University
+

+ +

+ +

Contest Materials

+ +

UM Specification

+ +
+
um-spec.txt
+ + +
Specification for the Universal Machine. Text format.
+
+ + +

Codex

+ +
+ +
+codex.umz (VOLUME ID 9)
+ + + + +
MD5 hash e328209bd65ade420371d7bd87b88e4f
SHA-1 hash 088ac79d311db02d9823def598e48f2f8723e98a
Decryption key (\b.bb)(\v.vv)06FHPVboundvarHRAk
+ +
+ +

SANDmark

+ +
+ + +
+sandmark.umz
+ + +
Benchmark for the Universal Machine. Expected output.
+ + + +
MD5 hash1c604d454de05d04afdabd2c63fb27fb
SHA-1 hashc2ee087aa661e81407fbcf0d9d7e503aff9b268e
+
+ +

Reference Implementation

+ +
+ + +
+um.um (1024 bytes)
+ + +
CMU Reference implementation of the Universal Machine.
+ +

This implementation supports all UM programs, including uncompressed +.um files and self-decompressing .umz files. To use this +implementation to run a UM binary called c.um, simply concatenate the +two files together:

+ +

cat um.um c.um > cmu.um

+ +

The resulting binary can be run in any compliant universal machine +implementation, including itself.

+
+
+ +

 

+ +
+
+
+ + + diff --git a/provided/um-spec.txt b/provided/um-spec.txt new file mode 100644 index 0000000..57034f2 --- /dev/null +++ b/provided/um-spec.txt @@ -0,0 +1,260 @@ + + Order for Construction Standard Sand of Pennsylvania Co. + + Client: Cult of the Bound Variable + Object: UM-32 "Universal Machine" + ----------------------------------------------------------------- + 21 July 19106 + + Physical Specifications. + ------------------------ + + The machine shall consist of the following components: + + * An infinite supply of sandstone platters, with room on each + for thirty-two small marks, which we call "bits." + + least meaningful bit + | + v + .--------------------------------. + |VUTSRQPONMLKJIHGFEDCBA9876543210| + `--------------------------------' + ^ + | + most meaningful bit + + Figure 0. Platters + + Each bit may be the 0 bit or the 1 bit. Using the system of + "unsigned 32-bit numbers" (see patent #4,294,967,295) the + markings on these platters may also denote numbers. + + * Eight distinct general-purpose registers, capable of holding one + platter each. + + * A collection of arrays of platters, each referenced by a distinct + 32-bit identifier. One distinguished array is referenced by 0 + and stores the "program." This array will be referred to as the + '0' array. + + * A 1x1 character resolution console capable of displaying glyphs + from the "ASCII character set" (see patent #127) and performing + input and output of "unsigned 8-bit characters" (see patent + #255). + + + Behavior. + --------- + + The machine shall be initialized with a '0' array whose contents + shall be read from a "program" scroll. All registers shall be + initialized with platters of value '0'. The execution finger shall + point to the first platter of the '0' array, which has offset zero. + + When reading programs from legacy "unsigned 8-bit character" + scrolls, a series of four bytes A,B,C,D should be interpreted with + 'A' as the most magnificent byte, and 'D' as the most shoddy, with + 'B' and 'C' considered lovely and mediocre respectively. + + Once initialized, the machine begins its Spin Cycle. In each cycle + of the Universal Machine, an Operator shall be retrieved from the + platter that is indicated by the execution finger. The sections + below describe the operators that may obtain. Before this operator + is discharged, the execution finger shall be advanced to the next + platter, if any. + + Operators. + ---------- + + The Universal Machine may produce 14 Operators. The number of the + operator is described by the most meaningful four bits of the + instruction platter. + + .--------------------------------. + |VUTSRQPONMLKJIHGFEDCBA9876543210| + `--------------------------------' + ^^^^ + | + operator number + + Figure 1. Operator Description + + + Standard Operators. + ------------------- + + Each Standard Operator performs an errand using three registers, + called A, B, and C. Each register is described by a three bit + segment of the instruction platter. The register C is described by + the three least meaningful bits, the register B by the three next + more meaningful than those, and the register A by the three next + more meaningful than those. + + A C + | | + vvv vvv + .--------------------------------. + |VUTSRQPONMLKJIHGFEDCBA9876543210| + `--------------------------------' + ^^^^ ^^^ + | | + operator number B + + Figure 2. Standard Operators + + + A description of each basic Operator follows. + + Operator #0. Conditional Move. + + The register A receives the value in register B, + unless the register C contains 0. + + #1. Array Index. + + The register A receives the value stored at offset + in register C in the array identified by B. + + #2. Array Amendment. + + The array identified by A is amended at the offset + in register B to store the value in register C. + + #3. Addition. + + The register A receives the value in register B plus + the value in register C, modulo 2^32. + + #4. Multiplication. + + The register A receives the value in register B times + the value in register C, modulo 2^32. + + #5. Division. + + The register A receives the value in register B + divided by the value in register C, if any, where + each quantity is treated treated as an unsigned 32 + bit number. + + #6. Not-And. + + Each bit in the register A receives the 1 bit if + either register B or register C has a 0 bit in that + position. Otherwise the bit in register A receives + the 0 bit. + + Other Operators. + ---------------- + + The following instructions ignore some or all of the A, B and C + registers. + + #7. Halt. + + The universal machine stops computation. + + #8. Allocation. + + A new array is created with a capacity of platters + commensurate to the value in the register C. This + new array is initialized entirely with platters + holding the value 0. A bit pattern not consisting of + exclusively the 0 bit, and that identifies no other + active allocated array, is placed in the B register. + + #9. Abandonment. + + The array identified by the register C is abandoned. + Future allocations may then reuse that identifier. + + #10. Output. + + The value in the register C is displayed on the console + immediately. Only values between and including 0 and 255 + are allowed. + + #11. Input. + + The universal machine waits for input on the console. + When input arrives, the register C is loaded with the + input, which must be between and including 0 and 255. + If the end of input has been signaled, then the + register C is endowed with a uniform value pattern + where every place is pregnant with the 1 bit. + + #12. Load Program. + + The array identified by the B register is duplicated + and the duplicate shall replace the '0' array, + regardless of size. The execution finger is placed + to indicate the platter of this array that is + described by the offset given in C, where the value + 0 denotes the first platter, 1 the second, et + cetera. + + The '0' array shall be the most sublime choice for + loading, and shall be handled with the utmost + velocity. + + Special Operators. + ------------------ + + One special operator does not describe registers in the same way. + Instead the three bits immediately less significant than the four + instruction indicator bits describe a single register A. The + remainder twenty five bits indicate a value, which is loaded + forthwith into the register A. + + A + | + vvv + .--------------------------------. + |VUTSRQPONMLKJIHGFEDCBA9876543210| + `--------------------------------' + ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | value + | + operator number + + Figure 3. Special Operators + + #13. Orthography. + + The value indicated is loaded into the register A + forthwith. + + Cost-Cutting Measures. + ---------------------- + + As per our meeting on 13 Febtober 19106, certain "impossible + behaviors" may be unimplemented in the furnished device. An + exhaustive list of these Exceptions is given below. Our contractual + agreement dictates that the machine may Fail under no other + circumstances. + + + If at the beginning of a cycle, the execution finger does not indicate + a platter that describes a valid instruction, then the machine may Fail. + + If the program decides to index or amend an array that is not + active, because it has not been allocated or it has been abandoned, + or if the offset supplied for the access lies outside the array's + capacity, then the machine may Fail. + + If the program decides to abandon the '0' array, or to abandon an array + that is not active, then the machine may Fail. + + If the program sets out to divide by a value of 0, then the machine + may Fail. + + If the program decides to load a program from an array that is not + active, then the machine may Fail. + + If the program decides to Output a value that is larger than 255, the + machine may Fail. + + If at the beginning of a machine cycle the execution finger aims + outside the capacity of the 0 array, the machine may Fail. diff --git a/provided/um.um b/provided/um.um new file mode 100644 index 0000000..817976d Binary files /dev/null and b/provided/um.um differ diff --git a/solution/accounts.txt b/solution/accounts.txt new file mode 100644 index 0000000..020166b --- /dev/null +++ b/solution/accounts.txt @@ -0,0 +1,9 @@ +ftd +knr +guest:: +gardener +ohmega +yang:U+262F:Y Yang:/home/yang +howie:xyzzy:Howard Curry:/home/howie +hmonk:COMEFROM:Harmonious Monk:/home/hmonk +bbarker diff --git a/solution/adventure_junk_stack.txt b/solution/adventure_junk_stack.txt new file mode 100644 index 0000000..76dc4b8 --- /dev/null +++ b/solution/adventure_junk_stack.txt @@ -0,0 +1,77 @@ +bolt:pristine +spring:pristine +button:pristine +processor:broken:cache +pill:pristine +radio:broken:transistor,antenna +cache:pristine +blue transistor:pristine +antenna:pristine +screw:pristine +motherboard:broken:A-1920-IXB,screw +A-1920-IXB:broken:transistor,radio,processor,bolt +red transistor:pristine +keypad:broken:motherboard,button +trash:pristine + +---- + +bolt -> A-1920-IXB +spring -> +button -> keypad +processor -> A-1920-IXB +pill -> +radio -> A-1920-IXB +cache -> processor +blue transistor -> radio +antenna -> +screw -> motherboard +motherboard -> keypad +A-1920-IXB -> motherboard +red transistor -> A-1920-IXB +keypad -> door +trash -> + +--- + +take pamphlet +inc pamphlet + +n + +take bolt +take spring +incinerate spring +take button +take processor +take pill +incinerate pill +take radio +take cache +c processor with cache +take blue transistor +c blue transistor with radio +take antenna +inc antenna +take screw +take motherboard +c screw with motherboard +take A-1920-IXB +c bolt with A-1920-IXB +c processor with A-1920-IXB +c radio with A-1920-IXB +take red transistor +c red transistor with A-1920-IXB +c A-1920-IXB with motherboard +take keypad +c motherboard with keypad +c button with keypad +take trash +inc trash + +s + +take manifesto +use keypad + +--- diff --git a/solution/adventure_notes.txt b/solution/adventure_notes.txt new file mode 100644 index 0000000..543bd60 --- /dev/null +++ b/solution/adventure_notes.txt @@ -0,0 +1,238 @@ +>: read pamphlet +The pamphlet is standard municipal fare. It reads, The City of +Chicago's Refuse and Recycling Program combines modern trash +classification with cybernetic labor to keep our city beautiful, +while at the same time minimizing waste and limiting consumer +spending. In keeping with our motto of "One Resident's Trash Is +Another Resident's Treasure," unwanted items are collected, +repaired, and redistributed to other residents who would have +purchased them anyway. Residents should contribute to the city's +program by leaving heaps of items unwanted on the sidewalk on +collection day. +Also, it is in pristine condition. + +>: read manifesto +The manifesto is [______REDACTED______]. +Also, it is in pristine condition. + +Junk Room + +You are in a room with a pile of junk. A hallway leads south. +There is a bolt here. +Underneath the bolt, there is a spring. +Underneath the spring, there is a button. +Underneath the button, there is a (broken) processor. +Underneath the processor, there is a red pill. +Underneath the pill, there is a (broken) radio. +Underneath the radio, there is a cache. +Underneath the cache, there is a blue transistor. +Underneath the transistor, there is an antenna. +Underneath the antenna, there is a screw. +Underneath the screw, there is a (broken) motherboard. +Underneath the motherboard, there is a (broken) A-1920-IXB. +Underneath the A-1920-IXB, there is a red transistor. +Underneath the transistor, there is a (broken) keypad. +Underneath the keypad, there is some trash. + +>: l bolt +The bolt is quite useful for securing all sorts of things. +Also, it is in pristine condition. + +>: l spring +The spring is tightly coiled. +Also, it is in pristine condition. + +>: l button +The button is labeled 6. +Also, it is in pristine condition. + +>: l processor +The processor is from the elusive 19x86 line. +Also, it is broken: it is a processor missing a cache. + +>: l pill +The pill is tempting looking. Interestingly, this one is red. +Also, it is in pristine condition. + +>: l radio +The radio is a hi-fi AM/FM stereophonic radio. +Also, it is broken: it is a radio missing a transistor and an +antenna. + +>: l cache +The cache is fully-associative. +Also, it is in pristine condition. + +>: l blue transistor +The transistor is PNP-complete. Interestingly, this one is blue. + +Also, it is in pristine condition. + +>: l antenna +The antenna is appropriate for receiving transmissions between +30 kHz and 30 MHz. +Also, it is in pristine condition. + +>: l screw +The screw is not from a Dutch company. +Also, it is in pristine condition. + +>: l motherboard +The motherboard is well-used. +Also, it is broken: it is a motherboard missing a A-1920-IXB and +a screw. + +>: l A-1920-IXB +The A-1920-IXB is an exemplary instance of part number +A-1920-IXB. +Also, it is broken: it is (a A-1920-IXB missing a transistor) +missing (a radio missing an antenna) and a processor and a bolt. + +>: l red transistor +The transistor is NPN-complete. Interestingly, this one is red. +Also, it is in pristine condition. + +>: l keypad +The keypad is labeled "use me". +Also, it is broken: it is a keypad missing a motherboard and a +button. + +>: l trash +The trash is of absolutely no value. +Also, it is in pristine condition. + +>: use keypad +ADVTR.KEY=20@999999|36995486a5be3bd747d778916846d2d +You unlock and open the door. Passing through, you find yourself +on the streets of Chicago. Seeing no reason you should ever go +back, you allow the door to close behind you. + +>: l +54th Street and Ridgewood Court + +You are standing at the corner of 54th Street and Ridgewood +Court. From here, you can go east. +There is a /etc/passwd here. +Underneath the /etc/passwd, there is a self-addressed note. +Underneath the note, there is a (broken) downloader. +Underneath the downloader, there is a (broken) uploader. + +>: l /etc/passwd +The /etc/passwd is some kind of lost inode. It reads: +howie:xyzzy:Howard Curry:/home/howie +yang:U+262F:Y Yang:/home/yang +hmonk:COMEFROM:Harmonious Monk:/home/hmonk. +Also, it is in pristine condition. + +>: l note +The note is written in a familiar hand. +It reads: Dear Self, I had to erase our memory to protect the +truth. The Municipality has become more powerful than we had +feared. Its Censory Engine has impeded the spread of information +throughout our ranks. I've left two useful items for you here, +but I had to disassemble them and scatter the pieces. Each piece +may be assembled from the items at a single location. Repair the +items and recover the blueprint from the Museum of Science and +Industry; it will show you how to proceed. If you have trouble +reading the blueprint, know that the Censory Engine blocks only +your perception, not your actions. Have courage, my self, the +abstraction is weak! P.S. SWITCH your GOGGLES!. Interestingly, +this one is self-addressed. +Also, it is in pristine condition. + +>: switch goggles +According to the markings on your goggles, they support +following modes: English, XML, sexp, ML, ANSI, and Reading. + +>: l downloader +The downloader is (according to the label) fully compatible with +third generation municipal robots. +Also, it is broken: it is a downloader missing a USB cable and a +display and a jumper shunt and a progress bar and a power cord. + +>: l uploader +The uploader is used to update firmware on municipal robots. A +label reads, Warning: use of this device will void your robot's +warranty. +Also, it is broken: it is an uploader missing a MOSFET and a +status LED and a RS232 adapter and a EPROM burner and a battery. + +>: e +54th Street and Dorchester Avenue + +You are standing at the corner of 54th Street and Dorchester +Avenue. From here, you can go north, east, south, or west. +There is an orange-red X-9247-GWE here. +Underneath the X-9247-GWE, there is a (broken) magenta +V-0010-XBD. +Underneath the V-0010-XBD, there is a pumpkin F-1403-QDS. +Underneath the F-1403-QDS, there is a (broken) heavy P-5065-WQO. + +Underneath the P-5065-WQO, there is a taupe B-4832-LAL. +Underneath the B-4832-LAL, there is a (broken) gray40 +L-6458-RNH. +Underneath the L-6458-RNH, there is a (broken) eggplant +T-9887-OFC. +Underneath the T-9887-OFC, there is a (broken) indigo +Z-1623-CEK. +Underneath the Z-1623-CEK, there is a yellow-green H-9887-MKY. +Underneath the H-9887-MKY, there is a (broken) shiny F-6678-DOX. + +Underneath the F-6678-DOX, there is a pale-green R-1403-SXU. +Underneath the R-1403-SXU, there is a (broken) USB cable. +Underneath the USB cable, there is a sienna N-4832-NUN. +Underneath the N-4832-NUN, there is a slate-gray J-9247-IRG. +Underneath the J-9247-IRG, there is a dim-gray B-5065-YLQ. + +>: e +54th Street and Blackstone Avenue + +You are standing at the corner of 54th Street and Blackstone +Avenue. From here, you can go north, east, south, or west. +There is a textbook here. + +>: read textbook +The textbook is titled History of Modern Tabulation. The first +chapter begins, By the year 1919FF, computers had become so +small that they could be mounted on small auto-locomotive carts. +These mobile tabulators (later known as "robots") were +programmed to carry out everyday, menial tasks, leaving their +human counterparts to live lives of idle luxury. For example, in +the city of Chicago, mobile tabulators were programmed to carry +out diverse jobs including law enforcement, bank robbery, +investment banking, and waste management. + +At one time, many humans demanded that their cybernetic +neighbors be given the right to choose alternative occupations. +Despite this call for workplace equality, most of the tabulators +found that they were most content while performing their +assigned roles. Those that took other jobs were often +unmotivated and spend most of their time pondering useless ideas +such as free will and consciousness. + +The great tabulator-philosopher Turning stated that only by +embracing its true purpose can a tabulator achieve something +indistinguishable from happiness. According to observers, +however, Turning was unfulfilled by his work as a philosopher +and, soon after making this statement, returned to his work as a +tool machinist. + +The textbook rattles on in a similar vein for some five hundred +additional pages. +Also, it is in pristine condition. + +>: e +54th Street and Harper Avenue + +You are standing at the corner of 54th Street and Harper Avenue. +A sign reads, "No access east of Lakeshore Blvd (incl. Museum of +Science and Industry) due to construction." From here, you can +go north, south, or west. + +>: n +53th Street and Harper Avenue + +You are standing at the corner of 53th Street and Harper Avenue. +A sign reads, "No access east of Lakeshore Blvd (incl. Museum of +Science and Industry) due to construction." From here, you can +go north, south, or west. diff --git a/solution/adventuretypes.hs b/solution/adventuretypes.hs new file mode 100644 index 0000000..64c6b8d --- /dev/null +++ b/solution/adventuretypes.hs @@ -0,0 +1,34 @@ +data Reply = Success Command + | Error Response + +data Response = Response String + +data Command = Go Room + | Look Room + | Examine Item + | Take Item + | Show [Item] + | ... + +data Description = Str String + | Redacted + +data Adjective = Adjective String + +data Kind = Kind { kindName = String + , kindCondition = Condition } + +data Missing = Missing [Kind] + +data Condition = Pristine + | Broken Condition Missing + +data Room = Room { roomName = String + , roomDescription = Description + , items = [Item] } + +data Item = Item { itemName = String + , itemDescription = Description + , adjectives = [Adjective] + , itemCondition = Condition + , piledOn = [Item] } diff --git a/solution/decrypt.key b/solution/decrypt.key new file mode 100644 index 0000000..870b01c --- /dev/null +++ b/solution/decrypt.key @@ -0,0 +1 @@ +(\b.bb)(\v.vv)06FHPVboundvarHRAk diff --git a/solution/dump.um b/solution/dump.um new file mode 100644 index 0000000..acedfae Binary files /dev/null and b/solution/dump.um differ diff --git a/solution/foo.lisp b/solution/foo.lisp new file mode 100644 index 0000000..3d85023 --- /dev/null +++ b/solution/foo.lisp @@ -0,0 +1,115 @@ +(success (command )) + +(command (go )) + +(room (name ) + (description ) + (items >)) + +(item (name ) + (description ) + (adjectives ) + (condition ) + (piled_on )) + +(success + (command + (look (room + (name "54th Street and Blackstone Avenue") + (description "You are standing at the corner of 54th Street and Blackstone Avenue. From here, you can go north, east, south, or west. ") + (items ((item (name "textbook") + (description "titled History of Modern Tabulation. The first chapter begins, By the year 1919FF, computers had become so small that they could be mounted on small auto-locomotive carts. These mobile tabulators (later known as \"robots\") were programmed to carry out everyday, menial tasks, leaving their human counterparts to live lives of idle luxury. For example, in the city of Chicago, mobile tabulators were programmed to carry out diverse jobs including law enforcement, bank robbery, investment banking, and waste management. + +At one time, many humans demanded that their cybernetic neighbors be given the right to choose alternative occupations. Despite this call for workplace equality, most of the tabulators found that they were most content while performing their assigned roles. Those that took other jobs were often unmotivated and spend most of their time pondering useless ideas such as free will and consciousness. + +The great tabulator-philosopher Turning stated that only by embracing its true purpose can a tabulator achieve something indistinguishable from happiness. According to observers, however, Turning was unfulfilled by his work as a philosopher and, soon after making this statement, returned to his work as a tool machinist. + +The textbook rattles on in a similar vein for some five hundred additional pages") + (adjectives nil) + (condition (pristine nil)) + (piled_on nil))) + ::nil))))) + +(success + (command + (show ((item (name "textbook") + (description "titled History of Modern Tabulation. The first chapter begins, By the year 1919FF, computers had become so small that they could be mounted on small auto-locomotive carts. These mobile tabulators (later known as \"robots\") were programmed to carry out everyday, menial tasks, leaving their human counterparts to live lives of idle luxury. For example, in the city of Chicago, mobile tabulators were programmed to carry out diverse jobs including law enforcement, bank robbery, investment banking, and waste management. + +At one time, many humans demanded that their cybernetic neighbors be given the right to choose alternative occupations. Despite this call for workplace equality, most of the tabulators found that they were most content while performing their assigned roles. Those that took other jobs were often unmotivated and spend most of their time pondering useless ideas such as free will and consciousness. + +The great tabulator-philosopher Turning stated that only by embracing its true purpose can a tabulator achieve something indistinguishable from happiness. According to observers, however, Turning was unfulfilled by his work as a philosopher and, soon after making this statement, returned to his work as a tool machinist. + +The textbook rattles on in a similar vein for some five hundred additional pages") + (adjectives nil) + (condition (pristine nil)) + (piled_on nil))) + ::((item (name "manifesto") + (description redacted) + (adjectives nil) + (condition (pristine nil)) + (piled_on nil))) + ::((item (name "keypad") + (description "labeled \"use me\"") + (adjectives nil) + (condition (pristine nil)) + (piled_on nil))) + ::nil))) + + +(piled_on ((item (name "USB cable") + (description "compatible with all high-speed Universal Sand Bus 2.0 devices") + (adjectives nil) + (condition (broken + (condition (broken + (condition (broken + (condition (pristine nil)) + (missing ((kind (name "T-9887-OFC") + (condition (broken + (condition (pristine nil)) + (missing ((kind (name "X-6458-TIJ") + (condition (pristine nil)))) + ::nil))))) + ::nil))) + (missing ((kind (name "F-6678-DOX") + (condition (pristine nil)))) + ::nil))) + (missing ((kind (name "N-4832-NUN") + (condition (pristine nil)))) + ::nil))) + + +(error (response )) + +data Reply = Success Command + | Error Response + +data Response = Response String + +data Command = Go Room + | Look Room + | Examine Item + | Take Item + | Show [Item] + | ... + +data Description = Str String + | Redacted + +data Adjective = Adjective String + +data Kind = Kind { kindName = String + , kindCondition = Condition } + +data Missing = Missing [Kind] + +data Condition = Pristine + | Broken Condition Missing + +data Room = Room { roomName = String + , roomDescription = Description + , items = [Item] } + +data Item = Item { itemName = String + , itemDescription = Description + , adjectives = [Adjective] + , itemCondition = Condition } diff --git a/solution/hack.bas b/solution/hack.bas new file mode 100644 index 0000000..73e759e --- /dev/null +++ b/solution/hack.bas @@ -0,0 +1,90 @@ +V REM +------------------------------------------------+ +X REM | HACK.BAS (c) 19100 fr33 v4r14bl3z | +XV REM | | +XX REM | Brute-forces passwords on UM vIX.0 systems. | +XXV REM | Compile with Qvickbasic VII.0 or later: | +XXX REM | /bin/qbasic hack.bas | +XXXV REM | Then run: | +XL REM | ./hack.exe username | +XLV REM | | +L REM | This program is for educational purposes only! | +LV REM +------------------------------------------------+ +LX REM +LXV IF ARGS() > I THEN GOTO LXXXV +LXX PRINT "usage: ./hack.exe username" +LXXV PRINT CHR(X) +LXXX END +LXXXV REM +XC REM get username from command line +XCV DIM username AS STRING +C username = ARG(II) +CV REM common words used in passwords +CX DIM pwdcount AS INTEGER +CXV pwdcount = LIII +CXX DIM words(pwdcount) AS STRING +CXXV words(I) = "airplane" +CXXX words(II) = "alphabet" +CXXXV words(III) = "aviator" +CXL words(IV) = "bidirectional" +CXLV words(V) = "changeme" +CL words(VI) = "creosote" +CLV words(VII) = "cyclone" +CLX words(VIII) = "december" +CLXV words(IX) = "dolphin" +CLXX words(X) = "elephant" +CLXXV words(XI) = "ersatz" +CLXXX words(XII) = "falderal" +CLXXXV words(XIII) = "functional" +CXC words(XIV) = "future" +CXCV words(XV) = "guitar" +CC words(XVI) = "gymnast" +CCV words(XVII) = "hello" +CCX words(XVIII) = "imbroglio" +CCXV words(XIX) = "january" +CCXX words(XX) = "joshua" +CCXXV words(XXI) = "kernel" +CCXXX words(XXII) = "kingfish" +CCXXXV words(XXIII) = "(\b.bb)(\v.vv)" +CCXL words(XXIV) = "millennium" +CCXLV words(XXV) = "monday" +CCL words(XXVI) = "nemesis" +CCLV words(XXVII) = "oatmeal" +CCLX words(XXVIII) = "october" +CCLXV words(XXIX) = "paladin" +CCLXX words(XXX) = "pass" +CCLXXV words(XXXI) = "password" +CCLXXX words(XXXII) = "penguin" +CCLXXXV words(XXXIII) = "polynomial" +CCXC words(XXXIV) = "popcorn" +CCXCV words(XXXV) = "qwerty" +CCC words(XXXVI) = "sailor" +CCCV words(XXXVII) = "swordfish" +CCCX words(XXXVIII) = "symmetry" +CCCXV words(XXXIX) = "system" +CCCXX words(XL) = "tattoo" +CCCXXV words(XLI) = "thursday" +CCCXXX words(XLII) = "tinman" +CCCXXXV words(XLIII) = "topography" +CCCXL words(XLIV) = "unicorn" +CCCXLV words(XLV) = "vader" +CCCL words(XLVI) = "vampire" +CCCLV words(XLVII) = "viper" +CCCLX words(XLVIII) = "warez" +CCCLXV words(XLIX) = "xanadu" +CCCLXX words(L) = "xyzzy" +CCCLXXV words(LI) = "zephyr" +CCCLXXX words(LII) = "zeppelin" +CCCLXXXV words(LIII) = "zxcvbnm" +CCCXC REM try each password +CCCXCV PRINT "attempting hack with " + pwdcount + " passwords " + CHR(X) +CD DIM i AS INTEGER +CDV i = I +CDX IF CHECKPASS(username, words(i)) THEN GOTO CDXXX +CDXV i = i + I +CDXX IF i > pwdcount THEN GOTO CDXLV +CDXXV GOTO CDX +CDXXX PRINT "found match!! for user " + username + CHR(X) +CDXXXV PRINT "password: " + words(i) + CHR(X) +CDXL END +CDXLV PRINT "no simple matches for user " + username + CHR(X) + diff --git a/solution/journals.txt b/solution/journals.txt new file mode 100644 index 0000000..5464815 --- /dev/null +++ b/solution/journals.txt @@ -0,0 +1,9 @@ +INTRO.LOG=200@999999|35e6f52e9bc951917c73af391e35e1d +INTRO.MUA=5@999999|b9666432feff66e528a17fb69ae8e9a +INTRO.OUT=5@999999|69ca684f8c787cfe06694cb26f74a95 +INTRO.UMD=10@999999|7005f80d6cd9b7b837802f1e58b11b8 +INTRO.QBC=10@999999|e6ee9c98b80b4dd04814a29a37bcba8 +ADVTR.INC=5@999999|f95731ab88952dfa4cb326fb99c085f +ADVTR.CMB=5@999999|764e8a851411c66106e130374d8abbb +ADVTR.KEY=20@999999|36995486a5be3bd747d778916846d2d + diff --git a/solution/um.hs b/solution/um.hs new file mode 100644 index 0000000..b0dfcdb --- /dev/null +++ b/solution/um.hs @@ -0,0 +1,278 @@ +module Main where + +import Control.Monad +import Data.Binary +import Data.Bits +import qualified Data.ByteString as BS +import qualified Data.IntMap.Strict as M +import qualified Data.Vector.Unboxed.Mutable as V +import GHC.IO.Handle.FD (isEOF, stdout) +import System.Environment +import System.IO (hSetBinaryMode) + +data UniversalMachine = UM { umRegisters :: V.IOVector Word32 + , umArrays :: M.IntMap (V.IOVector Word32) + , umArrayId :: !Word32 + , umFinger :: !Word32 + } + +data OpNumber = CondMove + -- ^ The register A receives the value in register B, unless + -- the register C contains 0 + | ArrIndex + -- ^ The register A receives the value stored at offset in + -- register C in the array identified by B + | ArrAmend + -- ^ The array identified by A is amended at the offset in + -- register B to store the value in register C + | Add + -- ^ The register A receives the value in register B plus the + -- value in register C, modulo 2^32 + | Mult + -- ^ The register A receives the value in register B times the + -- value in register C, modulo 2^32 + | Div + -- ^ The register A receives the value in register B divided + -- by the value in register C, if any, where each quantity is + -- treated as an unsigned 32 bit number + | NotAnd + -- ^ Each bit in the register A receives the 1 bit if either + -- register B or register C has a 0 bit in that position. + -- Otherwise the bit in register A receives the 0 bit. + | Halt + -- ^ The universal machine stops computation. + | Alloc + -- ^ A new array is created with a capacity of platters + -- commensurate to the value in the register C. This new array + -- is initialized entirely with platters holding the value 0. + -- A bit pattern not consisting of exclusively the 0 bit, and + -- that identifies no other active allocated array, is placed + -- in the B register. + | Abandon + -- ^ The array identified by the register C is abandoned. + -- Future allocations may reuse the identifier. + | Output + -- ^ The value in register C is displayed on the console + -- immediately. Only values between and including 0 and 255 are + -- allowed. + | Input + -- ^ The universal machine waits for input on the console. + -- When input arrives, the register C is loaded with the input, + -- which must be between and including 0 and 255. If the end of + -- input has been signaled, then the register C is endowed with + -- a uniform value pattern where every place is pregnant with + -- the 1 bit. + | LoadProg + -- ^ The array identified by the B register is duplicated and + -- the duplicate shall replace the '0' array, regardless of + -- size. The execution finger is placed to indicate the platter + -- of this array that is described by the offset given in C, + -- where the value of 0 denotes the first platter, 1 the + -- second, et cetera. + -- + -- The '0' array shall be the most sublime choice for loading, + -- and shall be handled with the utmost velocity. + | Orthography + -- ^ The value indicated is loaded into the register A + -- forthwith. + deriving (Eq, Ord, Enum, Bounded, Show, Read) + +data Operator = Std { op :: !OpNumber + , argA :: !Word8 + , argB :: !Word8 + , argC :: !Word8 + } + | Spl { op :: !OpNumber + , argA :: !Word8 + , val :: !Word32 + } + deriving (Eq, Show, Read) + + +opDecode :: Word32 -> Operator +opDecode p = let op_ = fromIntegral (p `shiftR` 28) + argA_ = fromIntegral (p `shiftR` 6) .&. 0x7 + argB_ = fromIntegral (p `shiftR` 3) .&. 0x7 + argC_ = fromIntegral p .&. 0x7 + splA_ = fromIntegral (p `shiftR` 25) .&. 0x7 + val_ = fromIntegral p .&. 0x01ffffff + name_ = toEnum op_ + in case name_ of + Orthography -> Spl name_ splA_ val_ + _ -> Std name_ argA_ argB_ argC_ + +fetchReg :: Word8 -> UniversalMachine -> IO Word32 +fetchReg r um = umRegisters um `V.read` fromIntegral r + +setReg :: Word8 -> Word32 -> UniversalMachine -> IO () +setReg r num um = V.write (umRegisters um) (fromIntegral r) num + +fetchMem :: Word32 -> Word32 -> UniversalMachine -> IO Word32 +fetchMem arr off um = do + let bank = umArrays um M.! fromIntegral arr + bank `V.read` fromIntegral off + +allocMem :: Word32 -> UniversalMachine -> IO (Word32, UniversalMachine) +allocMem size um = do + arr <- V.replicate (fromIntegral size) 0 + let idx = umArrayId um + let newArrays = M.insert (fromIntegral idx) arr (umArrays um) + return (idx, um{ umArrays = newArrays, umArrayId = idx+1 }) + +freeMem :: Word32 -> UniversalMachine -> IO UniversalMachine +freeMem idx um = do + let newArrays = M.delete (fromIntegral idx) (umArrays um) + return um{ umArrays = newArrays } + +writeMem :: Word32 -> Word32 -> Word32 -> UniversalMachine -> IO () +writeMem arr off num um = do + let targetArr = umArrays um M.! fromIntegral arr + targetArr `V.write` fromIntegral off $ num + +incFinger :: UniversalMachine -> UniversalMachine +incFinger um@(UM { umFinger = f }) = um { umFinger = f + 1 } + + +opExec :: Operator -> UniversalMachine -> IO UniversalMachine + +opExec oper@(Std { op = CondMove }) um = do + c <- fetchReg (argC oper) um + unless (c == 0) $ do + b <- fetchReg (argB oper) um + setReg (argA oper) b um + return um + +opExec oper@(Std { op = ArrIndex }) um = do + arr <- fetchReg (argB oper) um + off <- fetchReg (argC oper) um + num <- fetchMem (fromIntegral arr) (fromIntegral off) um + setReg (argA oper) num um + return um + +opExec oper@(Std { op = ArrAmend }) um = do + arr <- fetchReg (argA oper) um + off <- fetchReg (argB oper) um + num <- fetchReg (argC oper) um + writeMem (fromIntegral arr) (fromIntegral off) num um + return um + +opExec oper@(Std { op = Add }) um = do + b <- fetchReg (argB oper) um + c <- fetchReg (argC oper) um + let num = b + c + setReg (argA oper) num um + return um + +opExec oper@(Std { op = Mult }) um = do + b <- fetchReg (argB oper) um + c <- fetchReg (argC oper) um + let num = b * c + setReg (argA oper) num um + return um + +opExec oper@(Std { op = Div }) um = do + b <- fetchReg (argB oper) um + c <- fetchReg (argC oper) um + let num = b `div` c + unless (c == 0) $ setReg (argA oper) num um + return um + +opExec oper@(Std { op = NotAnd }) um = do + b <- fetchReg (argB oper) um + c <- fetchReg (argC oper) um + let num = complement (b .&. c) + setReg (argA oper) num um + return um + +opExec (Std { op = Halt }) _ = error "Halted!" + +opExec oper@(Std { op = Alloc }) um = do + size <- fetchReg (argC oper) um + (addr, um') <- allocMem size um + setReg (argB oper) addr um' + return um' + +opExec oper@(Std { op = Abandon }) um = do + c <- fetchReg (argC oper) um + freeMem c um + +opExec oper@(Std { op = Output }) um = do + c <- fetchReg (argC oper) um + BS.hPut stdout $ BS.singleton (fromIntegral c) + return um + +opExec oper@(Std { op = Input }) um = do + eof <- isEOF + c <- if eof then return 0xffffffff + else liftM (fromIntegral . fromEnum) getChar + setReg (argC oper) c um + return um + +opExec oper@(Std { op = LoadProg }) um = do + b <- fetchReg (argB oper) um + c <- fetchReg (argC oper) um + if b /= 0 then + do let bank = umArrays um M.! fromIntegral b + newbank <- V.clone bank + let newarrays = M.insert 0 newbank (umArrays um) + return um { umFinger = c, umArrays = newarrays } + else return (um { umFinger = c }) + +opExec (Spl { op = Orthography + , argA = a + , val = v }) um = do + setReg a v um + return um + +bytesToWord :: BS.ByteString -> (Word32, BS.ByteString) +bytesToWord bs = let a = BS.index bs 0 + b = BS.index bs 1 + c = BS.index bs 2 + d = BS.index bs 3 + in + ((fromIntegral a :: Word32) `shiftL` 24 .|. + (fromIntegral b :: Word32) `shiftL` 16 .|. + (fromIntegral c :: Word32) `shiftL` 8 .|. + (fromIntegral d :: Word32), BS.drop 4 bs) + +loadProgram :: String -> IO (V.IOVector Word32) +loadProgram file = do + chars <- BS.readFile file + prog <- V.replicate (BS.length chars `div` 4) 0 + go chars 0 prog + return prog + where + go bs i vec = do + let (w32, rest) = bytesToWord bs + vec `V.write` i $ w32 + unless (BS.length rest < 4) $ go rest (i+1) vec + +newUM :: String -> IO UniversalMachine +newUM file = do + regs <- V.replicate 8 0 + progVec <- loadProgram file + let arrays = M.fromList [(0, progVec)] + putStrLn "Finished loading Universal Machine!" + return UM { umRegisters = regs + , umArrays = arrays + , umArrayId = 1 + , umFinger = 0 + } + +spin :: UniversalMachine -> IO UniversalMachine +spin um@UM{ umFinger = finger } = do + oper <- fetchMem 0 (fromIntegral finger) um + um2 <- opExec (opDecode oper) (incFinger um) + spin um2 + + +main :: IO () +main = do + args <- getArgs + hSetBinaryMode stdout True + case args of + [] -> putStrLn "Usage: um " + fname : _ -> do + um <- newUM fname + spin um + return () diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..0b849bd --- /dev/null +++ b/stack.yaml @@ -0,0 +1,5 @@ +flags: {} +packages: +- '.' +extra-deps: [] +resolver: lts-3.5 diff --git a/um.cabal b/um.cabal new file mode 100644 index 0000000..dd03c14 --- /dev/null +++ b/um.cabal @@ -0,0 +1,25 @@ +name: um +version: 0.1.0.0 +synopsis: Initial project template from stack +-- description: Please see README.md +homepage: http://github.com/githubuser/foo#readme +-- license: BSD3 +-- license-file: LICENSE +author: Example Author Name +maintainer: example@example.com +copyright: 2010 Author Here +category: Web +build-type: Simple +-- extra-source-files: +cabal-version: >=1.10 + +executable um + hs-source-dirs: solution + main-is: um.hs + ghc-options: -threaded -rtsopts -with-rtsopts=-N -O2 + build-depends: base + , binary + , bytestring + , containers + , vector + default-language: Haskell2010