summaryrefslogtreecommitdiff log msg author committer range
blob: 6316c51fb62c5a29ac3ed552f22732487f687965 (plain)
 ```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 ``` ``````### Remarks Just run it with no argument: \$ ruby entry.rb I confirmed the following implementation/platform: - ruby 2.2.3p173 (2015-08-18 revision 51636) [x64-mingw32] ### Description The program is a [Piphilology](https://en.wikipedia.org/wiki/Piphilology#Examples_in_English) suitable for Rubyists to memorize the digits of [Pi](https://en.wikipedia.org/wiki/Pi). In English, the poems for memorizing Pi start with a word consisting of 3-letters, 1-letter, 4-letters, 1-letter, 5-letters, ... and so on. 10-letter words are used for the digit `0`. In Ruby, the lengths of the lexical tokens tell you the number. \$ ruby -r ripper -e \ 'puts Ripper.tokenize(STDIN).grep(/\S/).map{|t|t.size%10}.join' < entry.rb 31415926535897932384626433832795028841971693993751058209749445923078164062862... The program also tells you the first 10000 digits of Pi, by running. \$ ruby entry.rb 31415926535897932384626433832795028841971693993751058209749445923078164062862... ### Internals Random notes on what you might think interesting: - The 10000 digits output of Pi is seriously computed with no cheets. It is calculated by the formula `Pi/2 = 1 + 1/3 + 1/3*2/5 + 1/3*2/5*3/7 + 1/3*2/5*3/7*4/9 + ...`. - Lexical tokens are not just space-separated units. For instance, `a*b + cdef` does not represent [3,1,4]; rather it's [1,1,1,1,4]. The token length burden imposes hard constraints on what we can write. - That said, Pi is [believed](https://en.wikipedia.org/wiki/Normal_number) to contain all digit sequences in it. If so, you can find any program inside Pi in theory. In practice it isn't that easy particularly under the TRICK's 4096-char limit rule. Suppose we want to embed `g += hij`. We have to find [1,2,3] from Pi. Assuming uniform distribution, it occurs once in 1000 digits, which already consumes 5000 chars in average to reach the point. We need some TRICK. - `alias` of global variables was useful. It allows me to access the same value from different token-length positions. - `srand` was amazingly useful. Since it returns the "previous seed", the token-length `5` essentially becomes a value-store that can be written without waiting for the 1-letter token `=`. - Combination of these techniques leads to a carefully chosen 77-token Pi computation program (quoted below), which is embeddable to the first 242 tokens of Pi. Though the remaining 165 tokens are just no-op fillers, it's not so bad compared to the 1000/3 = 333x blowup mentioned above. big, temp = Array 100000000**0x04e2 srand big alias \$curTerm \$initTerm big += big init ||= big \$counter ||= 02 while 0x00012345 >= \$counter numbase = 0x0000 \$initTerm ||= Integer srand * 0x00000002 srand \$counter += 0x00000001 \$sigmaTerm ||= init \$curTerm /= srand pi, = Integer \$sigmaTerm \$counter += 1 srand +big && \$counter >> 0b1 num = numbase |= srand \$sigmaTerm += \$curTerm pi += 3_3_1_3_8 \$curTerm *= num end print pi - By the way, what's the blowup ratio of the final code, then? It's 242/77, whose first three digits are, of course, 3.14. ``````