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