Self-reproducing Spiral

n/a nforrett at wgz.com
Tue Jul 16 00:13:12 CDT 2002


On Mon, 15 Jul 2002, Tyler F. Creelan wrote:

> Can anyone explain how this (very awesome!) perl code works?

I've attached my attempt. Once you reformat the code in a sane manner, and see 
through all the distractions, it is not nearly so terrifying. =)

[snip]

-- 
Nick

 ,--< Nick Forrette >--------------------------.
 | e-mail: nforrett at wgz.org                    |
 | www   : http://www.drforehead.net/          |
 `---------------------------------------------'

-------------- next part --------------
On Mon, 15 Jul 2002, Tyler F. Creelan wrote:

> Can anyone explain how this (very awesome!) perl code works?
> 
> "This self-reproducing code prints a turning spiral filled with it's own
> code."
> 
> #!/usr/bin/perl
> $_='
>          $q ="\                   47"; wh
>         ile                           ($ ;=
>       $z                +=              .5 ){
>     %c=           $r=0;$/ ="";whi         le(2
>    0+          $z>($;+=.05)){$c{int$       _+ 2
>   6+         2*($              r+= .0       2) *
>  s          in$                   ;}{1       -$_
> +1         0+           int        $r*c       o s
> $         ;}         =1for(0.       .1)        }$
> t        =r         ever se;$        /.        =`
> c        le        ar     `.         "         #!
> /        usr       /bi             n/         pe
> rl       \n\       $_ =$q        \n"          ;
> fo        r$y        (1..20){$c{$_}          {
> $ y       }? $         /.=chop$t            :
>  ($/        . ="                          \4
>  0")         for(0.                    .53)          ;
>    $/.        ="\n"}pri            nt"$/$          q;
>    s; ".         chr(9 2)."s;;g;eval\n           "}

Set $_ to be a rather large string of (poorly) formatted perl code.
 
> ';s;\s;;g;

# Remove all the whitespace from $_

> eval

Evaluate the whitespaceless $_.

Now if we remove the whitespace earlier, and strategicly add some back in to 
clarify the ccdes intent, you get something like this...

$q = "\47" ;
while( $; = $z += .5) {
  %c = $r= 0 ;
  $/ = "" ;
  
  while( 20 + $z > ($; += .05)) {
    $c{int $_ + 26 + 2 * ($r += .02) * sin $;}{1 - $_ + 10 + int $r * cos $;} = 1 for(0 .. 1)
  }

  $t = reverse ;
  $/ . = `clear` . "#!/usr/bin/perl\n\$_=$q\n" ;

  for $y (1 .. 20) {
    $c{$_}{$y} ? $/ .= chop $t : ($/ .= "\40") for(0 .. 53);
    $/ .= "\n"
  }

  print "$/$q;s;" . chr(92) . "s;;g;eval\n"
}

With some added comments, and rewriting the inner while loop, you get 
the following.

# Set $q to ascii octal 47, or the single quote
$q = "\47" ;

# Increment the subscript separator (perldoc perlvar) and $z by .5
while( $; = $z += .5) {
  %c = $r = 0 ;

  # Set the INPUT_RECORD_SEPARATOR to the empty string (perldoc perlvar)
  $/ = "" ;
  
  # The first time through the outer loop...
  # Increment the subscript separator to .55, and loop while it is < 20+$z 
  # ($z is .5 at the start of the loop)
  while( 20 + $z > ($; += .05)) {
    
    # $_ == 0 and $r == 0    and $; == .55 the first time through the loop
    # $_ == 1 and $r ==  .02 and $; == .55 the second time through the loop
    for (0 .. 1) {
      # Set $c{26}{11} = 1 the first time through the loop
      # Set $c{27}{10} = 1 the second time through the loop
      $c{int $_ + 26 + 2 * ($r += .02) * sin $;}{1 - $_ + 10 + int $r * cos $;} = 1 ;
    }

    # Repeat the while loop, with $; (subscript separator) == .06
  }
  
  # $t is empty the first time through the outer loop
  $t = reverse ;

  # This clears the screen and represents the first two lines of replicated
  # code in each iteration of the outer while loop
  $/ . = `clear` . "#!/usr/bin/perl\n\$_=$q\n" ;

  # Some yet to be determined magic happens here. This combined with the
  # previous inner while/for loops eventually manages to recreate the
  # spiralized bit of code in the middle. If I was more familiar with how
  # sin/cos fit in with mathematical formulas for spirals, this would be a tad
  # easier. Maybe someone else could shed a little light (and/or wait for me
  # to do a bit more digging around).
  for $y (1 .. 20) {
    $c{$_}{$y} ? $/ .= chop $t : ($/ .= "\40") for(0 .. 53);
    $/ .= "\n"
  }
  
  # And here, you can forget all the other mumbo-jumbo in the previous while
  # loops, and sine/cosine stuff because the code never futzed with $q. 
  # It just clears the screen, prints the first two lines, the body of the 
  # code, and constructs the last two lines in not-terrible obvious manner
  # (ascii 92 is backslash).
  print "$/$q;s;" . chr(92) . "s;;g;eval\n"

  # Repeat the loop a bunch of times needlessly.
}



More information about the Pdx-pm-list mailing list