Google Answers Logo
View Question
 
Q: Explain Perl Code off T-Shirt ( Answered,   2 Comments )
Question  
Subject: Explain Perl Code off T-Shirt
Category: Computers > Programming
Asked by: killerhippo-ga
List Price: $5.00
Posted: 16 May 2003 04:41 PDT
Expires: 15 Jun 2003 04:41 PDT
Question ID: 204535
Please explain in detail the following Perl code I took off of a
t-shirt:

#!/usr/bin/perl  
## Perl Owns Me  
$e="\e[";for$r(0..62){for(0..11){($c,$y,$x)=(31&(620,5586,14053,496) 
         
[$_/3]>>5*($_%3),(7-($r/5))*($_%3-1),(11-($r/3))*(int($_/3)-2));print$_?"":$e."2J",$e,10-int(sin(3-$r/10)*$x-cos(3-$r/10)*$y),";",
  
40-int(cos(3-$r/10)*$x+sin(3-$r/10)*$y),H=>chr$c+($c?96:10)}select'','','',(30-$r)?.1:1}
Answer  
Subject: Re: Explain Perl Code off T-Shirt
Answered By: josh_g-ga on 16 May 2003 12:53 PDT
 
Hi killerhippo,

This Perl code has been deliberately structured to be difficult for a
human to read and comprehend, commonly known as obfuscated code.

obfuscate: To make so confused or opaque as to be difficult to
perceive or understand.
 - The American Heritage Dictionary
http://dictionary.reference.com/search?q=obfuscated

Usually, writing obfuscated code is a bad practice, since it makes it
more difficult for code to be understood, debugged, and reused. 
However, some programmers enjoy writing small programs of such
hard-to-read code as both a challenge to themselves and those reading
the code, and simply for fun.

The first obvious thing to do is run the code, and see what it does! 
It prints the message "perl owns me" in a nifty way, spinning the
letters around the screen in a spiral pattern that lines them up twice
to show the message.

The best way to work through this code is to convert it into a more
readable form.  The first step I took was to redo the line breaks to
match the actual lines of code:


#!/usr/bin/perl   
## Perl Owns Me   
$e="\e[";
for$r(0..62){
  for(0..11){
    ($c,$y,$x)=(31&(620,5586,14053,496)
[$_/3]>>5*($_%3),(7-($r/5))*($_%3-1),(11-($r/3))*(int($_/3)-2));

    print $_?"":$e."2J",$e,10-int(sin(3-$r/10)*$x-cos(3-$r/10)*$y),";",
40-int(cos(3-$r/10)*$x+sin(3-$r/10)*$y),H=>chr$c+($c?96:10)
   }
   select'','','',(30-$r)?.1:1
}


This gives us an assignment statement and two nesting for loops with
two very ugly looking lines inside.  The first line is another
variable assignment, but is actually assigning values to three
different variables.  So we can convert this:

   ($c,$y,$x)=(31&(620,5586,14053,496)
[$_/3]>>5*($_%3),(7-($r/5))*($_%3-1),(11-($r/3))*(int($_/3)-2));

to this:

   $c = 31 & (620,5586,14053,496) [$_/3]>>5*($_%3);
   $y = (7-($r/5)) * ($_%3-1);
   $x = (11-($r/3)) * (int($_/3)-2);

and the code works in the exact same way.  Our first guess, which
seems to be supported by the later print statement, is that $y and $x
are the screen co-ordinates where the current letter will be printed,
and $c represents what letter is being printed.  The functions for $y
and $x depend on the variable $r, which is incrementing as part of the
outermost for loop.

Note that the variable $_ which is used is actually a special global
variable, which in this case was assigned by the innermost for loop. 
Since the for loop didn't specify a variable, the loop value was
assigned to $_ by default.

So, glancing at the formulae for $y and $x, we can see how the
character positions change depending on both the current $r value
(which is basically a time value as the program steps forward through
the $r loop) and on which character is being printed (defined by the
innermost loop, assigned to the variable $_ ).  Note that the
int($_/3) function within the $x formula simply converts the value of
$_ divided by three into an integer.

Looking at the assignment statement for $c, the value is generated by
doing a bitwise AND with 31 and a value from the list
(620,5586,14053,496).  The list value used is indexed by [$_/3], and
then bitwise shifted right five times, and then multiplied by ($_%3). 
Note that % is the modulo operator, not a division.

Somehow, this arcane formula of bit-shifting and arithmetic seems to
be generating values which will become the ASCII values for the
letters "perl owns me" in the print statement later.  I don't have
time to step through the math and watch it work.  Since the program
actually runs, I'm going to use the experimental evidence to support
this analysis. ;)

The print statement itself is a nightmare!

print $_?"":$e."2J",$e,10-int(sin(3-$r/10)*$x-cos(3-$r/10)*$y),";",
40-int(cos(3-$r/10)*$x+sin(3-$r/10)*$y),H=>chr$c+($c?96:10)

The print function takes a comma-separated list of things to be
printed to the screen, so let's visually split this statement apart by
the commas:

print $_?"":$e."2J",
      $e,
      10-int(sin(3-$r/10)*$x-cos(3-$r/10)*$y),
      ";", 
      40-int(cos(3-$r/10) * $x+sin(3-$r/10)*$y),
      H=>chr$c+($c?96:10)

Recall that $e was assigned to a string value earlier.  While this
still looks a bit cryptic, the quick explanation is that this print
command is using ANSI control characters to do cursor movement on the
screen, and then print the appropriate character.  The $x and $y
values affect the cursor movement, and $c is used to generate the
character itself (using the chr function).

I don't have time to look up further details and pull apart the exact
workings of the last couple statements - if you still have any
specific (brief) questions on the code, you could mention it in a
clarification.

Thanks,
 - josh_g-ga
Comments  
Subject: Re: Explain Perl Code off T-Shirt
From: robertskelton-ga on 16 May 2003 05:15 PDT
 
Seems to be something known as obfuscated perl:
http://www.linux.net.nz/lists/NZLUG/2001/08/0542.html

My guess (I don't know Perl, and I don't know what obfuscated means)
is that it is a program that displays "Perl Owns Me" on the screen.

Because:

- it is using co-ordinates
- for(0..11) indicates 12 things, and the phrase has 12 characters,
including spaces.

If you like this sort of stuff, check out:

The Obfuscated Perl Contest Archives
http://www.sysadminmag.com/tpj/obfuscated/

PS - must be quite an ugly t-shirt :)
Subject: Re: Explain Perl Code off T-Shirt
From: vorfeed-ga on 16 May 2003 12:39 PDT
 
When I tried this program, it did indeed print "Perl Owns Me", only it
makes the letters float about in a circle before they come together
into the phrase. I don't know enough Perl to explain how it does it,
though, because it is quite thoroughly obfuscated.

As for "obfuscated" itself, it's a term that programmers use to
describe unclear  or unreadable code. For instance, variable names
that have nothing to do with what they contain are said to be
obfuscated, as are practices like using numerical codes to describe
text, or ignoring the proper placement of brackets and spacing. The
above example contains examples of all three.

In recent years, creating purposely obfuscated programs has become
something of a hobby for some. This led to the creation of the
Obfuscated Perl contest that robertskelton_ga mentioned.

I hope someone out there has greater Perl skills than I, though,
because I'm at a loss to explain how this one actually works.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy