You are on page 1of 4
#!/usr/bin/env perl # * cperl BEGIN { $W=1} use strict; use diagnostics; use warnings; use Carp; use English; use Math::Trig; use GD; use constant P| => 4*atan(1); # June 30, 2007 # Allan Peda # # Ulam prime number spiral # http://mathworld.wolfram.conyPrimeSpiral.html # http://en.wikipedia.org/wiki/Ulam_ spiral # # we iterate over a grid, but we want to follow a spiral # Direction is cartesian based x being horizontal motion, # and y being vertical. Up and right are postive motion. unless (defined ($ARGV[0])){ die "Please provide a png file to save to."; } my $pnogfile = ‘ulam_spiral.pno' if($ARGV[O] =~ nv\.pnaS/i){ $pngfile = $ARGV[0]; } else { print "Supplied file not suffixed with .png defaulting to \"$pngfile\".\n"; } # how many turns to make in the spiral my $num_corners = 1600; my @turning_points = mkturns($num_corners) ; # which directions do we follow my $max = $turning_points [$#turning_points ]; print "Generating map for first $max primes.\n"; my ($x width, $y width) = (0,0); $xwidth = $y width = int(sqrt($max+.5)); print "Dimensions are: $x width x $y_width\n"; my %primes = %{genprimes($max)}; my $im new GD: :Image($x_width, $y_width) ; my $white $im->colorAllocate (255,255,255) i my $black $im->colorAllocate(0,0,0) ; my $origin_color = $im->colorAllocate(255,0,0) ; my $position=$turning points [0] ; my ($x, $y) = (0,0); my (Sdelx,$dely) = (1,0); # start out moving to the right sub gdx { return( shift()+($x_width/2) ) } sub gdy { return( ($y_width/2)-shift()) } $im->setPixel (gdx($x) , gdy($y) , $origin_color) ; foreach my $next_turn (@turning points) { for (my Si=$position;$i<$next_turn;++$i) { # move to next cartesian $x t= $delx; $y 4= $dely; # print "x=$x, y=$y (i = $i)\n"; if ($i==$next_tum) { ($delx, $dely) = nextDirection($delx,$dely) ; if ( defined ($primes{$it1})) { # origin starts at n=1, not n=0 # translation to gd coordinate system $im->setPixel (gdx ($x) ,gdy($y) ,$black) ; + $position = $next_tum+1; open (PNGFH, '>".$pngfile) or die "Could not open image file \"$pngfile print PNGFH $im->png; close PNGFH; # an array of run lengths up to each turn # equation was guessed at after inspection of coordinates # froma hand drawn cartesian spiral sub mkturns{ my $ulim my $len hift; my @rv; foreach my $i (1..$ulim) { my $delta = ($i%2?$i+1:$1)/2; $len = $len+$delta; push( @rv, $len); return @rv; # generates prime numbers as hash keys sub genprimes { my $max = my $sieve my %primes = (2 => 1); GUESS: for (my $guess = 2; $guess <= $max; $guesstt) { next GUESS if vec($sieve,$guess,1) ; $primes{$guess} = 1; for (my $mults = $guess * $guess; $mults <= $max; $mults += $guess) - vec ($sieve, $mults,1) = 1; hift; } return \%primes; # uses memoized trig function # function modded to go past 180 degrees { my %memo = (); sub nextDirection { my ($x, $y) = (shift, shift); my $nextoffset = undef; if( defined ($memo{$x}{$y})){ $nextoffset = $memo{$x}{$y}; } else { my $acos = acos($x); my $asin = asin($y); if( $asin < O){ $asin+=(PI*2) ; + my $offset = int(2*($acos>$asin?$acos:$asin) /PI) ; # hard coded count of four directions in spiral (right, up, left down) $nextoffset = $memo{$x}{$y} = (Soffset+1)%4; } return to_xy($nextoffset) ;

You might also like