There are even a few solutions I still haven't figured out yet. I need
to break down the dense code from _why to get a handle on what's going
on.
I assume we're talking about this:
require 'rbconfig'
bui = /^bui(.{2})$/
$stdout << "#{{}.class}"[0,1] <<
("#{{}.methods}"[/c(\w{4})c/] && $1.reverse) <<
(([0]*2).inspect[2,2]) <<
Config::CONFIG.keys.grep(bui).first.gsub(bui,
"#{Kernel.methods.grep(/^th/)[0][2,3].reverse}\\1") <<
ObjectSpace._id2ref(338)
Yeah, that's crazy. Let's see if we can figure it out.
require 'rbconfig'
Require Ruby's configuration details. That gives us a bunch of fresh
Strings to work with.
bui = /^bui(.{2})$/
Define a regular expression that matches words like "build."
$stdout << "#{{}.class}"[0,1] <<
From here on out, it's all output. This creates a Hash, and pulls
the first character off of that class name.
("#{{}.methods}"[/c(\w{4})c/] && $1.reverse) <<
Now it starts to get tricky. This code pulls the methods for a Hash,
joins them into a giant String, uses a Regexp to find "collec" from the
collect() method, and reverses and prints the "olle" portion. That gets
us the rest of "Hello."
(([0]*2).inspect[2,2]) <<
This makes an Array, grabs the code for it from Ruby's inspect(), and
indexes into that String to pull out the comma and space.
Config::CONFIG.keys.grep(bui).first.gsub(bui,
"#{Kernel.methods.grep(/^th/)[0][2,3].reverse}\\1") <<
This uses the Regexp built a while back to match the "build" key out of
Ruby's configuration Hash. It then replaces the letters "bui." To get
the replacement, the code hunts for the throw() method on Kernel, pulls
the last three letters and reverses them. That gives us "wor" + "ld" or
"world."
ObjectSpace._id2ref(338)
I have no idea how reliable this is, but in _why's build of Ruby, and my
own, the object with the ID 338 is the Symbol :"!", the last character
needed.
Clever code as always from _why.
And I'm somewhat frightened to even contemplate the mind of Rubén
MedellÃn, whose solution is some bizarre, palindromic mirror image of
Ruby insanity.
It was freaking awesome. I'll leave it to someone else too spoil that
one…
James Edward Gray II
def method_missing(a = p, *c); return ; nruter ;(c* p = a);gnissim_dohtem fed
end ; dne
These first two lines define method_missing (in Object context) to do nothing. The code returns immediately (at return),
so none of the addional reversed names are executed. The dne after the end of method_missing calls method_missing, since no
method named dne is defined. We can now delete most mangled names that we don't understand. The equivalent code for this
is:
def method_missing (a=p, *c); return; end
The p is never evaluated (it would point to nowhere, or cause infinite recursion), because method_missing
is always called with the name of an argument
alias m method_missing ; gnissim_dohtem m; saila
class NilClass ; ssalCliN ssalc
alias inspect to_s ; s_ot tcepsni ;saila
end ; dne
NilClass.inspect now returns an empty string. Everything to the right of the semicolons is a call to method_missing.
This can be safely removed since it's never called anyway.
class Integer ; regetnI ssalc
def method_missing(a=chr,*b);print chr;return a.to_s[0] ; [0];s_ot.a nruter;rhc tnirp;(b*rhc=a);gnissim_dohtem fed
end ; dne
Supposing we call 63.method_missing directly. Then a will be ascii character 63 ('?'), and the function will print '?' and
return 63. Supposing we call 72.e. Then a will be the letter 'e'. The function will print ascii character 72 ('h') and return
the ascii code for 'e' (101). We can now call (for example) puts 72.e.l.l.o.chr and get the output 'Hello'
def d! ; return(d.e and puts) ; (stup dna; e.d);nruter ; !d fed
dne ; end ; dne ; end
Still operating on the integer context, this prints the previous letter, then a 'd' (through two missing methods)
and uses puts to place a blank line after the d.
The 2 end calls close the method p, and close the Integer class.
def p(p = a, *b) ; begin ; nigeb ; (b* a = p); p fed
rescue ; print p.to_s ; return ; nruter ; s_ot.p tnirp ; eucser
dne ; end ; dne ; end
Sorting out some of the method_missing calls:
def p(p=nil, *b)
begin
a=p #evalutes p as a variable
p fed #evaluates p as a function, causing a SystemStackError
rescue #catches the SystemStackError
#this is caught at the innermost level of the stack overflow
print p.to_s #evaluates p as a variable, which at the inner level is nil, so this prints nothing
return
end
end
The whole function definition can be safely removed, as called, it does the same thing as method_missing anyway.
dne def a b = c ; return nil ; lin nruter ; c = b a; fed end
Defines a method a which returns nil. dne calls method_missing with a nil argument. Since "def" to define a method is an
expression that returns nil, its return value can be passed to a function. This line can be safely removed since it
defines a method that does the same thing as method_missing.
a = a def fed a = a
return nruter
a = p end ; fed ; def dne p = a
p a ; a p
end ; dne
He breaks palindrome with a single semicolon here.
Sets the variable a to nil, (because the second a is a method call), and defines the method fed to return
the return value of nruter (which at this moment is a method_missing call, and stays that way for the rest of the program)
The line
a = p end
is acutally two statements: an a=p, followed by an end.
He then goes to immediately define dne to call the p function we saw before, which prints nothing, and
the a function which returns nil. So dne is now defined, but does nothing.
These 5 lines can actually all be safely removed, since they define methods which do the same thing as method_missing anyway.
def h ax0=0xa;return 0xa unless ax0;dne;y=x p;fed = def p x=y;end; 0xa;sselnu ax0;nruter ax0=0xa;h fed
bx0, dx0 = 0xd, 0xb
bx0 + dx0 + 0xb + bx0 + 0xd + 0xb
end ; dne
def h ax0=10
return 10 unless ax0
y=nil
fed = nil
def p x=y
end
bx0=13
dx0=11
bx0 + dx0 + 11 + bx0 + 13 + 11 # equals 13 + 11 + 11 + 13 + 13 + 11 which is 72
end
In short, if nil is explicitly passed to h, it returns 10. If anything else (or nothing) is passed to h,
it defines p (in the global context) to do nothing, then returns 72 (ascii for 'H').
def Object.const_missing a ; a gnissim_tsnoc.tcejbO; fed
return send(a.to_s.downcase) ; (esacnwod.s_ot.a);dnes nruter
end ; dne
All the stuff on the right side of the semicolons does nothing. The const_missing is intended to
convert the H constant reference on the next line to a call to the h method we just defined. (This will
return the ascii code for 'H', which is what we need to start the sequence of Integer.method_missing calls
on the next line.
H.e.l.l.o._.w.o.r.l.d! ; !d.l.r.o.w._.o.l.l.e.H
The left side prints out the string "Hello_world" using the integer method_missing chaining that I mentioned above. (The last
call to d! prints out the letter "d", as mentioned above.)
The right side calls the global method_missing repeatedly, which does nothing.
In other words, all of this code actually translates to:
(Everything else is calls method_missing which returns nil,
or calls a method which is functionally equivalent to method_missing.)
class Integer
def method_missing a, *b
print chr
return a.to_s[0]
end
def d!
return (d.e and puts)
end
end
def h
return 72
end
def Object.const_missing a
return send(a.to_s.downcase)
end
H.e.l.l.o._.w.o.r.l.d!