Re: camel code (SPOILERS!)
by jima (Vicar) on Dec 06, 2000 at 22:56 UTC
|
And at the risk of spoiling the fun by dissecting the camel, here's my attempt at describing what's going on here, because it's a pretty neat trick, and may encourage other ObWriters to experiment on their own. (People who don't want the fun spoiled should tune out now...)
The program basically reads its own source code, and prints out a smaller version of the Camel picture, by reducing the image by 50%. It does this by splitting the code up into 2*2 blocks of characters, figuring out which characters in this block are non-whitespace, and printing out a corresponding character to display the picture. Characters range from a " " (for a 4x4 block of spaces) to "X" (for a 4x4 block of non-whitespace).
The picture is created, stored in an array, and printed out twice (the strings are reversed during the first print, so that the 2nd set of camels are facing the other way). After the picture printout, the O'Reilly disclaimer is printed out.
Here's my annotated version of the code. Note that, since the formatting has been removed and comments added, this code will not work the same as the original. It's just meant for a study aid.
#!/usr/bin/perl -w # camel code
use strict;
$_='
eval("seek\040DATA,0,0;"); # clever way of seeking to beginning
+ of program file!
foreach (1..3) { # skip the first 3 lines (shebang, use str
+ict, and a blank line)
<DATA>;
}
my @camel1hump; # variable def's
my $camel;
my $Camel;
# for each line read, grab the following line (if there is another
# one to read), and go through the individual characters, detectin
+g
# whitespace and nonwhitespace characters.
#
# If you think of the image as being divided into 2x2 character
# blocks, then each char in the block will be assigned a power of
# 2 thusly:
#
# +---+---+
# | 8 | 4 |
# +---+---+
# | 2 | 1 |
# +---+---+
#
# For each block, this while block will add up the corresponding
# numbers for each nonwhiteapce char, resulting in a number stored
# in $camel1hump from 0 to 15. This number will then be translated
# to a ASCII picture character from ' ' (for a value of 0,
# indicating 4 whitespace characters) to 'X' (for a value of 15,
# indicating 4 nonwhitespace chars). These picture chars will be
# stored in the string $camel, to be printed out in a fancy way
# below.
while (<DATA>) {
$_ = sprintf("%-69s", $_); # format string in 69 columns
my @dromedary1 = split(//); # split $_ into individual char
+s
if (defined($_ = <DATA>)) { # get next line and split,
@camel1hump=split(//); # if it exists
}
while (@dromedary1) { # for each char
my $camel1hump = 0; # this var will hold the bits
my $CAMEL = 3; # this var is the bit #
if (defined($_ = shift(@dromedary1)) && /\S/) { # if the n
+ext char is a nonspace,
$camel1hump += 1<<$CAMEL; # add 1<<3 (8) to our
+ bit counter
}
$CAMEL--; # next bit...
if (defined($_ = shift(@dromedary1)) && /\S/) { # if th
+e next char is a nonspace,
$camel1hump += 1<<$CAMEL; # add 1<<2 (4) to our
+ bit counter
}
$CAMEL--; # next bit...
if(defined($_=shift(@camel1hump)) && /\S/) { # if the n
+ext char is a nonspace,
$camel1hump += 1<<$CAMEL; # add 1<<1 (2) to our
+ bit counter
}
$CAMEL--; # next bit...
if(defined($_ = shift(@camel1hump)) && /\S/) { # if the
+ next char is a nonspace,
$camel1hump+=1<<$CAMEL; # add 1<<0 (1) to o
+ur bit counter
;
}
# pick out the proper corresponding text format char for t
+he
# added-up bits. This could be non-obfuscated as a substr(
+)
# call.
$camel .= (split(//,"\040..m`{/J\047\134}L^7FX"))[$camel1h
+ump];
}
$camel .= "\n";
}
@camel1hump = split(/\n/,$camel); # split the picture into indi
+vidual lines
# Now we print the picture out. The same block of code is included
# twice in the program. The reason the second set of cames is reve
+rsed
# is because the reverse() function call actually does reverse the
+
# string in the @camel1hump array, so the second time the strings
+are
# printed, we get a flipped picture.
foreach (@camel1hump) {
chomp;
$Camel=$_;
# a bit of obfuscation which just translates 8 of the formatti
+ng chars
# to the digits "1" through "8", and then back again.
y/LJF7\173\175`\047/\061\062\063\064\065\066\067\070/;
y/12345678/JL7F\175\173\047`/;
$_=reverse; # reverse the string in $_ (which reverses
+it in the @camel1hump array)
print"$_\040$Camel\n"; # and print out reversed string, alo
+ng with the $Camel copy.
}
# and do basically the same thing again. Since the strings were re
+versed in the preceding
# block, they're printed out as flipped images of the camel.
foreach (@camel1hump) {
chomp;
$Camel=$_;
y/LJF7\173\175`\047/12345678/;
y/12345678/JL7F\175\173\0 47`/;
$_=reverse;
print "\040$_$Camel\n";
}
'; # and that's the end of $_. Whew.
;
s/\s*//g; # remove all spacing from $_
;
eval; # display the camels
eval("seek\040DATA,0,0;"); # seek back to the beginning of program
undef$/;
$_=<DATA>; # slurp in all the program into $_
s/\s*//g; # remove space
( );
;
s;^.*_;;; # remove all characters until the final "_", which will b
+e the last underscore in "__DATA__"
# Now print out the O'Reilly disclaimer. The chars in __DATA__
# are just the ASCII values, coded in octal. (And you thought
# the picture data was there!)
map { # this map statement
eval "print\"$_\""; # prints out each octal character
} # that it finds
/.{4}/g; # using this pattern match.
__DATA__
\124\150\145\040\165\163\145\040\157\146
\040\141\040\143\141\155\145\154\040\151
\155\141\147\145\040\151\156\040\141\163
\163\157\143\151\141\164\151\157\156\040
\167\151\164\150\040\120\145\162\154\040
\151\163\040\141\040\164\162\141\144\145
\155\141\162\153\040\157\146\040\117\047
\122\145\151\154\154\171\040\046\012\101
\163\163\157\143\151\141\164\145\163\054
\040\111\156\143\056\040\125\163\145\144
\040\167\151\164\150\040\160\145\162\155
\151\163\163\151\157\156\056
Whew. Is it lunchtime yet?
Update: Thanks to Erudil for pointing out that the y/// lines, which I thought were purely for obfuscatory (ooh!) purposes, actually serve a purpose. Namely, to translate non-symmetrical characters to their mirror image. "L" and "J" are exchanged, "F" and "7" are exchanged, etc. (Take a close look at the ordering of the characters in those two y/// lines.)
As an example of why this needs to be done, look at the camels' heads:
.mm. .mm.
.XXX^XLmm mmJX^XXX.
.XXXXXXXXXX XXXXXXXXXX.
{XXXXXX^^^' `^^^XXXXXX}
XXXXXXL JXXXXXX
See those "L"s and "J"s? If they hadn't been switched with the y/// code, the picture wouldn't have the dark portions in the right areas, and the picture wouldn't be a mirror image:
.mm. .mm.
.XXX^XLmm mmLX^XXX.
.XXXXXXXXXX XXXXXXXXXX.
{XXXXXX^^^' `^^^XXXXXX}
XXXXXXL LXXXXXX
| [reply] [d/l] |
|
++s all around. And kudos to you for interpreting the obfuscated code for those perl { not so experts } of us around here! =]
-marius
| [reply] |
|
| [reply] |
Re: camel code
by mrmick (Curate) on Dec 07, 2000 at 19:57 UTC
|
Wonderful!!
Just thinking... wouldn't this make a great t-shirt?
I'm going to print this off and show it to a couple of
colleagues here. Maybe that'll get them more into Perl.
Very imaginative! Cheers, Mick
Mick | [reply] |
|
A T-Shirt is actually a good idea. Code on front,
output of code on back. If Perlmonks produced the shirt, I'd
definitly spend money on it. (Are you listening, vroom? :)
-Ted
| [reply] |
|
He might not have been listening, but ThinkGeek was! Note the shirt version is slightly different; Erudil was even able to include a short comment. (Perhaps a new category should now be added to the Perl geek code: "My code has been used on a T-shirt".)
| [reply] |
|
Re: camel code
by r.joseph (Hermit) on Dec 07, 2000 at 04:20 UTC
|
This is absolutely awesome. I printed this out just to put on my wall because, like the penguin poster at ThinkGeek (the poster of the kernel source), code REALLY CAN be art. Not only is this an awesome program, but it looks great next to my camel book :-). Amazing job, and thanks for allowing me to prove to everyone who disbelieves that programming IS art :-).
R.Joseph | [reply] |
Blinded by the light...
by MeowChow (Vicar) on Dec 07, 2000 at 10:50 UTC
|
Looking at this camel code has a really odd and disturbing effect on my vision. After I take my eyes out of focus to view the camel, I find that for the next minute, I have a very hard time reading any text on my monitor, as text keeps going in and out of focus.
It's better now, but when I started writing this, I could barely discern what I was typing and there was even a moment when I thought there might be something wrong with my monitor.
Try looking at the camel as you would a 3D-stereogram. It it just me?
ps. amazing code, Erudil | [reply] |
|
"Try looking at the camel as you would a 3D-stereogram. It it just me?"
I think you just gave me the coolest obf idea ever...
| [reply] |
|
A badge for extreme cleverness goes to Erudil.
To jbeninger:
If I get your gist your thinking of forming a stereoscopic picture from
source code? Cool, but can I advise a lie down in a dark room for a few hours.
This could be construed as a challenge, but it would be phenomenal to see
that even attempted. I'm sure it could be done but every character
will need to be right to produce the desired effect, or it would need to be BIG
- and stand well back.
Good luck with it.
| [reply] |
|
Re: camel code
by Adam (Vicar) on Dec 06, 2000 at 22:01 UTC
|
The master strikes again! ++Erudil | [reply] |
Re: camel code
by myocom (Deacon) on Dec 07, 2000 at 04:31 UTC
|
Hee. A minor note: Running 'perl' and just pasting this in (which I do for many obfuscations) doesn't work so well, thanks to the seeks, I suspect. | [reply] |
Re: camel code
by princepawn (Parson) on May 22, 2001 at 00:40 UTC
|
We can all make Camel code now, thanks to
Smirch
| [reply] |
|
Few words to repeat the obvious thing : it's REALLY an amazing obfuscation...
Thanks to such code, my willingness to learn Perl keeps increasing :)
Arnaud
| [reply] |
Re: camel code
by ZX (Novice) on Dec 31, 2000 at 03:33 UTC
|
this is some very cool obfuscated code! ++Erudil! | [reply] |
Re: camel code
by spacewarp (Pilgrim) on Apr 07, 2001 at 02:49 UTC
|
I'm still relatively new to obfuscated programming, so I just have to wonder.. How long did this take to write??
Spacewarp
DISCLAIMER:
Use of this advanced computing technology does not imply an endorsement
of Western industrial civilization.
| [reply] |
Re: camel code
by demerphq (Chancellor) on Jul 07, 2004 at 20:13 UTC
|
Ah, just so you know this throws loads of warnings under 5.8.5 RC1 :
Newline in left-justified string for sprintf at (eval 1) line 1, <DATA
+> line 4.
...
:-)
---
demerphq
First they ignore you, then they laugh at you, then they fight you, then you win.
-- Gandhi
| [reply] [d/l] |
|
Just change the shebang line.
Change the -w to a -X (the warnings will no longer be displayed):
#!/usr/bin/perl -X #camel code
| [reply] |
|
| [reply] |
Re: camel code
by Anonymous Monk on Dec 07, 2004 at 05:46 UTC
|
You are the master... I dont know how you got this good... but I'm chassing after you... :) | [reply] |
Re: camel code
by Anonymous Monk on Feb 12, 2012 at 18:53 UTC
|
Dear Sir, I am replying from Italy
I am interested to this image as the possible cover image for a book I will publish within few months.
I like it because it abstractly expresses some of the basic issues of the book, a book about education and professional formation.
I wonder if you would give me the authorization to use such image for my cover, mentioning the source, naturally, and promising to send you a copy of the book, if you want, as soon as published (even if, being written in italian, it could be not so interesting for you).
thanks a lot
Maurizio Bonfanti
mail maurizio.bonfanti@fastwebnet.it
| [reply] |
|
| [reply] |
|
| [reply] |
|
| [reply] |