Beefy Boxes and Bandwidth Generously Provided by pair Networks Frank
Your skill will accomplish
what the force of many cannot
 
PerlMonks

camel code

by Erudil (Prior)
 | Log in | Create a new user | The Monastery Gates | Super Search | 
 | Seekers of Perl Wisdom | Meditations | PerlMonks Discussion | 
 | Obfuscation | Reviews | Cool Uses For Perl | Perl News | Q&A | Tutorials | 
 | Poetry | Recent Threads | Newest Nodes | Donate | What's New | 

on Dec 06, 2000 at 17:41 UTC ( #45213=obfuscated: print w/ replies, xml ) Need Help??

#!/usr/bin/perl -w # camel code use strict; $_='ev al("seek\040D ATA,0, 0;");foreach(1..3) {<DATA>;}my @camel1hump;my$camel; my$Camel ;while( <DATA>){$_=sprintf("%-6 9s",$_);my@dromedary 1=split(//);if(defined($ _=<DATA>)){@camel1hum p=split(//);}while(@dromeda ry1){my$camel1hump=0 ;my$CAMEL=3;if(defined($_=shif t(@dromedary1 ))&&/\S/){$camel1hump+=1<<$CAMEL;} $CAMEL--;if(d efined($_=shift(@dromedary1))&&/\S/){ $camel1hump+=1 <<$CAMEL;}$CAMEL--;if(defined($_=shift( @camel1hump))&&/\S/){$camel1hump+=1<<$CAMEL;}$CAMEL--;if( defined($_=shift(@camel1hump))&&/\S/){$camel1hump+=1<<$CAME L;;}$camel.=(split(//,"\040..m`{/J\047\134}L^7FX"))[$camel1h ump];}$camel.="\n";}@camel1hump=split(/\n/,$camel);foreach(@ camel1hump){chomp;$Camel=$_;y/LJF7\173\175`\047/\061\062\063\ 064\065\066\067\070/;y/12345678/JL7F\175\173\047`/;$_=reverse; print"$_\040$Camel\n";}foreach(@camel1hump){chomp;$Camel=$_;y /LJF7\173\175`\047/12345678/;y/12345678/JL7F\175\173\0 47`/; $_=reverse;print"\040$_$Camel\n";}';;s/\s*//g;;eval; eval ("seek\040DATA,0,0;");undef$/;$_=<DATA>;s/\s*//g;( );;s ;^.*_;;;map{eval"print\"$_\"";}/.{4}/g; __DATA__ \124 \1 50\145\040\165\163\145\040\157\1 46\040\1 41\0 40\143\141 \155\145\1 54\040\1 51\155\ 141 \147\145\0 40\151\156 \040\141 \163\16 3\ 157\143\ 151\141\16 4\151\1 57\156 \040\167 \151\164\1 50\040\ 120\1 45\162\ 154\040\15 1\163\ 040\14 1\040\1 64\162\1 41\144 \145\ 155\14 1\162\ 153\04 0\157 \146\ 040\11 7\047\ 122\1 45\15 1\154\1 54\171 \040 \046\ 012\101\16 3\16 3\15 7\143\15 1\14 1\16 4\145\163 \054 \040 \111\156\14 3\056 \040\ 125\163\145\14 4\040\ 167\1 51\164\1 50\0 40\160\ 145\162 \155\151 \163\163 \151\1 57\156\056

Comment on camel code
Download Code
Re: camel code
by Adam (Vicar) on Dec 06, 2000 at 22:01 UTC
    The master strikes again! ++Erudil
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
      ++s all around. And kudos to you for interpreting the obfuscated code for those perl { not so experts } of us around here! =]

      -marius
      jima:

      Nice analysis... But I'd suggest you use the <spoiler> and </spoiler> tags to make it a bit simpler to avoid the spoilers...

      ...roboticus
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
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.
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

      "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...

        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.

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
      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
        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".)
Re: camel code
by ZX (Novice) on Dec 31, 2000 at 03:33 UTC
    this is some very cool obfuscated code! ++Erudil!
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.
Re: camel code
by princepawn (Parson) on May 22, 2001 at 00:40 UTC
    We can all make Camel code now, thanks to Smirch
      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
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


      Just change the shebang line.

      Change the -w to a -X (the warnings will no longer be displayed):

      #!/usr/bin/perl -X              #camel code

        IIRC this silly warning has been removed from Perl in a later version (thank god).


        ---
        demerphq

          First they ignore you, then they laugh at you, then they fight you, then you win.
          -- Gandhi

          Flux8


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... :)

Login:
Password
remember me
What's my password?
Create A New User

Node Status?
node history
Node Type: obfuscated [id://45213]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (18)
GrandFather
jdporter
syphilis
Gavin
Jenda
atcroft
Khen1950fx
kennethk
herveus
dHarry
jkva
ssandv
Lady_Aleena
kalle
jau
AndyZaft
Neighbour
tart
As of 2010-09-09 06:49 GMT
Sections?
Seekers of Perl Wisdom
Cool Uses for Perl
Meditations
PerlMonks Discussion
Categorized Q&A
Tutorials
Obfuscated Code
Perl Poetry
Perl News
See About the sections of PerlMonks
Information?
PerlMonks FAQ
Guide to the Monastery
What's New at PerlMonks
Voting/Experience System
Tutorials
Reviews
Library
Perl FAQs
Other Info Sources
Find Nodes?
Nodes You Wrote
Super Search
List Nodes By Users
Newest Nodes
Recently Active Threads
Selected Best Nodes
Best Nodes
Worst Nodes
Saints in our Book
Leftovers?
The St. Larry Wall Shrine
Offering Plate
Awards
Craft
Snippets Section
Code Catacombs
Quests
Editor Requests
Buy PerlMonks Gear
PerlMonks Merchandise
Planet Perl
Perlsphere
Use Perl
Perl.com
Perl 5 Wiki
Perl Jobs
Perl Mongers
Perl Directory
Perl documentation
CPAN
Random Node
Voting Booth?

My favourite poll on PerlMonks is ...

Your first Perl Book - the first one ever
Average number of caffeinated beverages per work day - the poll with the highest participation
My Thoughts on the New Voting/Experience System - the poll with the fewest votes cast
When I grow up, I want to be: - one of the polls with the fewest options
Perl 6 will primarily be: - the first one on Perl6
When I see a poll - one of the many polls about polls
this poll ;-)
yet to come
none - I hate polls. Bah.
some other

Results (130 votes), past polls