Not logged in
Overview
SHA1 Hash: 48a095494dce96adb08a9f8ada7b95bd6c3ad1a3 2011-09-05 15:12:40 crc more master theorem solutions family | ancestors | descendants | both | trunk files | manifest
Tags And Properties
Changes
[hide diffs]    [patch]
```@@ -0,0 +1,26 @@
+( A Puzzle involving Math                       )
+( Or more specifically, the Pythagorean Theorem )
+( "For a right triangle with legs a and b and   )
+( hypotenuse c:  a^2 + b^2 = c^2                )
+
+
+needs math'
+
+: toIndex ( c-n )
+  'a - 1+ ;
+
+: h 'h toIndex ;
+: o 'o toIndex ;
+: f 'f toIndex ;
+: c 'c toIndex ;
+
+: ^2 ( n-n )  2 pow ;
+
+: toAlpha  ( n-c )
+  'a 1- + ;
+
+: x1 h ^2 o ^2 + ^math'squareRoot     toAlpha putc ;
+: x2 h ^2 f ^2 + ^math'squareRoot 2 / toAlpha putc ;
+: x3 5 ^2 c ^2 - ^math'squareRoot     toAlpha putc ;
+
+: solve  x1 x2 x3 ;

```

```@@ -0,0 +1,48 @@
+Flag semaphores are at the heart of this puzzle. In the text,
+M provides a series of times. These correspond to flag semaphore
+positions. If you picture the flag positions as the hands on an
+analog clock, this should become clear.
+
+So:
+
+  715 130 625 730 925 745 730 915 700
+
+These are our times.
+
+  : display ( n- )
+    [ 730 = ] [ drop 'A putc ] when
+    [ 130 = ] [ drop 'E putc ] when
+    [ 625 = ] [ drop 'G putc ] when
+    [ 745 = ] [ drop 'H putc ] when
+    [ 700 = ] [ drop 'K putc ] when
+    [ 715 = ] [ drop 'M putc ] when
+    [ 915 = ] [ drop 'R putc ] when
+    [ 925 = ] [ drop 'S putc ] when ;
+
+Less elegant than a lookup table, but suitable for this
+quick and dirty solution. Map each time to a character
+and display them.
+
+  "" ^buffer'set
+
+Setup a temporary string as a buffer.
+
+  depth [ ^buffer'add ] times
+
+Adds all of the times to the buffer.
+
+  ^buffer'start ^strings'reverse
+
+Reverse the order of the buffer, and leave a pointer...
+
+  [ @ display ] ^types'STRING each@
+
+And apply a quote to each item in the buffer. This is pretty
+simple: fetch the item, and give it to the display function.
+
+
+All in all, a boring puzzle. Once you figure out that M wants
+you to use flag semaphores in place of times, it's easy to find
+

```

```@@ -0,0 +1,63 @@
+This is pretty easy. Each code name is based on particular characters from
+the facts about each star. For example, the star named "water":
+
+Type: taurus
+Age: 1 billion years
+Distance: 18 x 10^10 light years
+Temperature: 5000 K
+Color: white
+
+The name comes from the first character of the color, the age, the first
+character of the type, the temperature (divide by 1000), and the distance
+(ignore the 10^10 part). The numbers correspond to the letters of the
+alphabet, with an index value of one.
+
+So to start, the alphabet, with the zero position filled by an underscore:
+
+  : letters "_abcdefghijklmnopqrstuvwxyz" ;
+
+Easy enough. Next, an array of variables. I'm going to use a trick here,
+which needs some explanation. Variables created with *elements* have their
+data stored sequentially, with headers being separated. So we can access
+them as a unit or structure later.
+
+  6 elements color age type temperature distance padding
+
+There is an used padding variable. This will be useful later.
+
+
+  : getNumber getToken toNumber ;
+  : toLetter letters + @ ;
+
+The first function, *getNumber*, parses and returns a number from the
+input stream. The second takes an index value and returns the corresponding
+letter from the alphabet.
+
+With these, we can now implement functions for each fact.
+
+  : Type: getToken @ !type ;
+  : Age: getNumber toLetter !age 2getToken 2drop ;
+  : Distance: getNumber toLetter !distance 2 [ 2getToken 2drop ] times ;
+  : Temperature: getNumber 1000 / toLetter !temperature getToken drop ;
+  : Color: getToken @ !color ;
+
+This is all a bit messy, but for a quick solution, it'll work. Each "fact"
+handler parses the input stream, extracts the character code (doing any
+adjustments needed), and sets the appropriate variable to the characters.
+
+Once these are defined, we can paste in the facts about our unknown star:
+
+Type: main
+Age: 1 billion years
+Distance: 14 x 10^10 light years
+Temperature: 5000 K
+Color: red
+
+And now we have an answer:
+
+  color puts
+
+Note here that we treat our variables as a string. Since the values are
+sequential the unused *padding* variable acts as a null terminator and
+ we don't need to do anything else to get the correct answer of *ramen*.

```

```@@ -0,0 +1,183 @@
+( The first part of the puzzle is a table, with six rows of six )
+( characters. We'll create a table to hold this data:           )
+
+  : table:  ( n"- )
+    create [ getToken @ , ] times ;
+
+( First up, a helper function that'll parse and build the tables. )
+( Pass it a count, and follow it by the table name, then a        )
+( whitespace delimited series of tokens.                          )
+
+  36 table: initial   A B C D E F
+                      G H I J K L
+                      M N O P Q R
+                      S T U V W X
+                      Y Z 0 1 2 3
+                      4 5 6 7 8 9
+
+( The initial table. This is an exact match to the table shown.   )
+
+  36 table: colors    1 2 3 4 2 5
+                      6 7 8 6 3 1
+                      9 5 0 5 7 A
+                      B C Q C D 4
+                      8 7 0 4 B 3
+                      7 D Q 5 A 9
+
+( The table of characters has colors. Each color is matched to )
+( two characters. We have a second table with values that      )
+( represent the color arrangement.                             )
+
+
+  : clue  ( -\$ )
+    "25 BACON BITS VANILLA 29 BROWNIES AND ALLSPICE 2" ;
+
+( Below the table is a string of text that encodes the answer to )
+( this puzzle. We create a string named "clue" to hold this.     )
+
+  : withToken ( \$q- )
+   [ " " ^strings'prepend " " ^strings'append ] dip
+   [ [ 32 ^strings'splitAtChar ^strings'chop ] dip [ do ] sip over 1 <> ] while 2drop ;
+
+( You aren't expected to understand this. Breaking it down: )
+
+   [ " " ^strings'prepend " " ^strings'append ] dip
+
+( Adds a space before and after the string passed to the          )
+( withToken function. This simplifies the following bits of code. )
+
+   [ [ 32 ^strings'splitAtChar ^strings'chop ] dip [ do ] sip over 1 <> ] while 2drop ;
+
+( This isn't too complex. Breaking it down further:        )
+
+   [ .... ] while 2drop
+
+( Everything is inside a while loop. The 2drop removes the )
+( pointers when execution is finished.                     )
+
+   [ 32 ^strings'splitAtChar ^strings'chop ] dip
+
+( Inside the loop, this temporarily hides the quote, splits )
+( a whitespace delimited token off the string, and removes  )
+( the trailing space with ^strings'chop.                    )
+
+  [ do ] sip
+
+( Execute the quote, keeping a copy of the pointer on the stack after  )
+( execution completes.                                                 )
+
+  over 1 <>
+
+( The condition for the while loop. When no tokens remain, the pointer )
+( value will be returned as "1". So if not 1, there are more tokens to )
+( process.                                                             )
+
+( In actual use, this is pretty nice. It means you can do things like: )
+
+  "hello 123 again" [ "Token: %s\n" puts ] withToken
+
+( The quote will be executed once for each word in the string. Now,    )
+( back to the solution.                                                )
+
+  : append
+    dup isNumber? [ [ @ ^buffer'add ] ^types'STRING each@ ]
+                  [ @ ^buffer'add ] if ;
+
+( This is a factor of the simplify function which we'll look at next.  )
+( It looks at a token to see if it's a number or a word. If it's a     )
+( number, each character in the string is added to a buffer. If it's a )
+( word, then only the first character is added.                        )
+
+( Note the use of each@, another combinator which allows a quote to be )
+( executed for each item in a data structure.                          )
+
+  : simplify ( \$-\$ )
+    heap [ here ^buffer'set 128 allot
+           &append withToken ] preserve
+    ^buffer'start ;
+
+( The rules of the puzzle dictate that each numeric digit has a color, )
+( and each word has a color. simplify compresses a string into just the)
+( relevant subset. To break this down:                                 )
+
+  heap [ ... ] preserve
+
+( We'll use the heap as a buffer. Encasing the code using this buffer  )
+( in a preservation quote cleans up any allocations when we are done.  )
+
+  here ^buffer'set
+
+( Sets the buffer to the heap.                                         )
+
+  128 allot
+
+( Allocates space for our buffer. This will be rolled back after       )
+( preserve is executed.                                                )
+
+  &append withToken
+
+( Applies the append function to each token in a string. We could also )
+( have specified this as:                                              )
+
+  [ append ] withToken
+
+( The & syntax is a shortcut for single-function quotes.               )
+
+  ^buffer'start
+
+( When execution of simplify finishes, we'll return a pointer to the   )
+( buffer we created.                                                   )
+
+  : getIndex  ( c-n )
+    initial [ [ @ over <> ] sip 1+ swap ] while nip initial - 1- ;
+
+( Lookup a character in the initial array, and return the index value  )
+( for later use.                                                       )
+
+  : colorize  ( \$-\$ )
+    simplify
+    "" tempString ^buffer'set
+    [ @ getIndex colors + @ ^buffer'add ] ^types'STRING each@ ^buffer'start ;
+
+( Convert a raw string into a colored one.                             )
+
+  simplify
+
+( Start by reducing to just the relevant data.                         )
+
+  "" tempString ^buffer'set
+
+( Create an empty string to use as a buffer.                           )
+
+  [ @ getIndex colors + @ ^buffer'add ] ^types'STRING each@
+
+( Use each@ to apply a quote to each character in the simplified       )
+( string. For each character, we find the index, lookup the            )
+( corresponding character in the colors array, and add that to the new )
+( string.                                                              )
+
+  ^buffer'start
+
+( Returns the colored string.                                          )
+
+( We're almost there. All we need to do is decode the colored string.  )
+
+  : match? ( n-nf )
+    [ colors + @ over = ] sip swap ;
+  : matches
+    [ @ 36 [ match? [ initial + @ putc ] [ drop ] if ] iter drop space ] ^types'STRING each@ ;
+
+( This is a quick hack to remap a color to all matching characters.    )
+( Since each color corresponds to two characters, this will display    )
+( pairs of characters.                                                 )
+
+( With this, we can do:                                                )
+
+  clue colorize matches
+
+( And we get the following output:                                     )
+(  S2 W5 BE BE TV S2 M9 BE AL AL S2                                    )
+( From this, it's easy to deduce the solution:                         )
+(  S  W   E  E T  S  M   E  L  L S                                     )
+( Or:                                                                  )
+(  SWEET SMELLS                                                        )

```

```@@ -0,0 +1,63 @@
+This puzzle involves finding a hidden message, encoded using a series of digits in various
+numeric bases.
+
+Given M's habit of hiding subtle clues in the article text, there are a number of references to
+*basement*. It's rather opaque, but the only real significance is that the puzzle somehow
+involves work with various bases.
+
+There are two parts to the puzzle: a column of shapes on the left, and a series of colored
+and/or shaped tiles on the right. Each row is in a different base. The shape on the left tells
+which base (count the number of sides), the tiles on the right encode the digits of each
+number.
+
+Solid colored tiles are zero, the others are the number of sides in the priamry shape.
+
+So:
+
+  : convertToDecimal:  ( n"-n )
+    base ! getToken toNumber decimal ;
+
+Pass this a base, and it'll parse a number and return the decimal form.
+
+With this, we can convert the numbers:
+
+  5 convertToDecimal: 0032
+  8 convertToDecimal: 0025
+  3 convertToDecimal: 0100
+  2 convertToDecimal: 1110
+  6 convertToDecimal: 0001
+  4 convertToDecimal: 0102
+  7 convertToDecimal: 0034
+
+Now to translate to ASCII. First, a string containing the letters. This has an _ as the first
+character. Since the results of M's puzzles have thus far been using an index of 1 rather than
+0, this lets us avoid incrementing each value by 1.
+
+  : alpha   ( -\$ )
+    "_abcdefghijklmnopqrstuzwxyz" ;
+
+Next up is a function to translate an integer into an ASCII character. Simply add the integer
+to the address returned by alpha, and fetch the stored character.
+
+  : toAlpha ( n-c )
+    alpha + @ ;
+
+Easy enough. Now to simplify building a string. We'll use the buffer' vocabulary for this.
+First, create a temporary string and then set it as the buffer.
+
+  "" tempString ^buffer'set
+
+Next, translate each value returned by convertToDecimal: to an ASCII code and add it to the
+buffer:
+
+  depth [ toAlpha ^buffer'add ] times
+
+And finally display the result:
+
+  ^buffer'start puts
+
+At this point, the resulting string is "yraniuq", which is reversed from what we want. So to
+fix it:
+
+  ^buffer'start ^strings'reverse puts
+

```

```@@ -0,0 +1,23 @@
+( Plenty of words in the text, but some stand out. The ones with )
+( colors have sounds in common with various numbers.             )
+
+( The trick to this puzzle is to group by color, and add the     )
+( numeric values up. So:                                         )
+
+( red     altitude foresight              2  4       ->  6       )
+( purple  intended wonder foreground     10  1  4    -> 15       )
+( blue    before to to tension            4  2  2 10 -> 18       )
+( green   attention pretend              10 10       -> 20       )
+( yellow  magnitude elated tenderly once  2  8 10  1 -> 21       )
+( gray    fate fortitude                  8  4  2    -> 14       )
+( pink    tonight to someones             2  2  1    ->  5       )
+
+( And then we can map the final values to alphabetic characters: )
+
+needs array'
+
+( remap so that 1 = a, 2 = b, and so on )
+: toAlpha ( n-c )
+  96 + ;
+
+^array'new{ 6 15 18 20 21 14 5 } [ toAlpha putc ] ^array'apply

```