#!/usr/local/bin/perl use strict; use Tk; die "Usage: \$0 max_number\n" # use the command-line, Luke! if ( @ARGV != 1 or \$ARGV[0] !~ /^\d+/ ); my \$lastnumber = shift; my ( \$mincoord, \$midcoord, \$maxcoord ) = ( 50, 250, 450 ); plot_grid( compute_primes( \$lastnumber )); MainLoop; { # closure for building prime number hash structure my @sorted_primes = ( 1 ); # primes in ascending order my %primecoord = ( 1 => [\$midcoord, \$midcoord] ); # HoA: keys are primes, values are x/y coords in grid sub ck_prime { my ( \$num, \$x, \$y ) = @_; my \$end = int( sqrt( \$num )); my \$keep = 1; for my \$prime ( @sorted_primes ) { if ( 0 == \$num % \$prime ) { \$keep = 0; last; } elsif ( \$prime > \$end ) { last; } } if ( \$keep ) { \$primecoord{\$num} = [ \$x, \$y ]; push @sorted_primes, \$num; } } sub compute_primes { # list of directions for incrementing x, y coordinates: my %vector = ( 0 => [ 1, 0 ], # rightward 1 => [ 0, 1 ], # downward 2 => [ -1, 0 ], # leftward 3 => [ 0, -1 ], # upward ); my \$x = my \$y = 250; # starting position my \$direction = 0; # changes when we've gone \$pathlen steps my \$traveled = 0; # no. of points drawn in current direction my \$pathlen = 1; # increments on every second direction change my \$changes = 0; # no. of dir. changes since last \$pathlen increment my \$number = 1; my \$bgn = time; while ( ++\$number <= \$lastnumber ) { \$x += \$vector{\$direction}[0]; \$y += \$vector{\$direction}[1]; last if ( \$x < \$mincoord or \$x > \$maxcoord ); if ( ++\$traveled == \$pathlen ) { \$direction = ++\$direction % 4; \$traveled = 0; if ( ++\$changes % 2 == 0 ) { \$changes = 0; \$pathlen++; } } ck_prime( \$number, \$x, \$y ); } my \$end = time; warn "Checked \$lastnumber integers in ", \$end - \$bgn, " sec\n"; return( \@sorted_primes, \%primecoord ); } } sub plot_grid { my ( \$primes, \$coords ) = @_; my \$mw = MainWindow->new; my \$c = \$mw->Canvas(-width => \$maxcoord+50, -height => \$maxcoord+50, -background => 'white' )->pack; \$c->createLine( \$mincoord, \$midcoord, \$maxcoord, \$midcoord ); \$c->createText( \$mincoord-30, \$midcoord, -fill => 'blue', -text => 'X'); \$c->createLine( \$midcoord, \$mincoord, \$midcoord, \$maxcoord ); \$c->createText( \$midcoord, \$mincoord-30, -fill => 'blue', -text => 'Y'); my \$bgn = time; for my \$prime ( @\$primes ) { my ( \$x, \$y ) = @{\$\$coords{\$prime}}; \$c->createText( \$x, \$y, -fill => 'black', -text => "\xb7" ); } my \$end = time; warn "Plotted ", scalar @\$primes, " primes in ", \$end - \$bgn, " sec\n"; }