The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl -w

# Copyright 2010, 2011 Kevin Ryde

# This file is part of Math-PlanePath.
#
# Math-PlanePath is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3, or (at your option) any later
# version.
#
# Math-PlanePath is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with Math-PlanePath.  If not, see <http://www.gnu.org/licenses/>.


use 5.010;
use strict;
use warnings;
use POSIX ();
use List::Util 'min', 'max';

# uncomment this to run the ### lines
use Smart::Comments;


{
  # vs spectrum
  require Image::Base::Text;
  my $prev = 0;
  my $diff_total = 0;
  my $diff_count = 0;
  my $prev_count = 0;
  my $prev_sq = 0;
  foreach my $r (1 .. 6000) {
    my $count = image_count($r) / 4;
    my $dcount = $count - $prev_count - 1;
    my $xfrac = (1 + sqrt(8*($r+0)**2-1))/4;
    # my $x = (2 + sqrt(8*($r+0)**2-4))/4;
    my $y = int($xfrac+.5);
    my $x = int($xfrac);
    my $extra = (($y-1)**2 + ($y+.5)**2) < $r*$r;
    $extra = ($x==$y); # && (($x^$y^1)&1);
    my $sq = $y + $y-1 + $extra;
    my $dsq = $sq - $prev_sq;
    my $star = ($dsq != $dcount ? "***" : "");
    # printf "%2d dc=%3d dsq=%4.2f  %s\n", $r, $dcount,$dsq, $star;

    $star = (int($sq) != $count ? "***" : "");
    printf "%2d c=%3d sq=%4.2f x=%4.2f,y=$y  %s\n", $r, $count,$sq,$x, $star;

    $prev_count = $count;
    $prev_sq = $sq;
  }
  exit 0;

  sub floor_half {
    my ($n) = @_;
    return int(2*$n)/2;
  }
}

{
  my $r = 5;
  my $w = 2*$r+1;
  require Image::Base::Text;
  my $image = Image::Base::Text->new (-width => $w,
                                      -height => $w);
  $image->ellipse (0,0, $w-1,$w-1, 'x');
  my $str = $image->save_string;
  print $str;
  exit 0;
}
{
  # wider ellipse() overlaps, near centre mostly
  my %image_coords;
  my $offset = 100;
  my $i;
  {
    package MyImageCoords;
    require Image::Base;
    use vars '@ISA';
    @ISA = ('Image::Base');
    sub new {
      my $class = shift;
      return bless {@_}, $class;
    }
    sub xy {
      my ($self, $x, $y, $colour) = @_;
      my $key = "$x,$y";
      if ($image_coords{$key}) {
        $image_coords{$key} .= ',';
      }
      $image_coords{$key} .= $i;
    }
  }
  my $width = 500;
  my $height = 494;
  my $image = MyImageCoords->new (-width => $width, -height => $height);
  for ($i = 0; $i < min($width,$height)/2; $i++) {
    $image->ellipse ($i,$i, $width-1-$i,$height-1-$i, $i % 10);
  }
  foreach my $coord (keys %image_coords) {
    if ($image_coords{$coord} =~ /,/) {
      print "$coord  i=$image_coords{$coord}\n";
    }
  }
  exit 0;
}
{
  # wider ellipse()
  require Image::Base::Text;
  my $width = 40;
  my $height = 10;
  my $image = Image::Base::Text->new (-width => $width, -height => $height);
  for (my $i = 0; $i < min($width,$height)/2; $i++) {
    $image->ellipse ($i,$i, $width-1-$i,$height-1-$i, $i % 10);
  }
  $image->save('/dev/stdout');
  exit 0;
}


{
  # average diff step 4*sqrt(2)
  require Image::Base::Text;
  my $prev = 0;
  my $diff_total = 0;
  my $diff_count = 0;
  foreach my $r (1 .. 1000) {
    my $count = image_count($r);
    my $diff = $count - $prev;
 #   printf "%2d %3d  %2d\n", $r, $count, $diff;
    $prev = $count;
    $diff_total += $diff;
    $diff_count++;
  }
  my $avg = $diff_total/$diff_count;
  my $sqavg = $avg*$avg;
  print "diff average $avg squared $sqavg\n";
  exit 0;
}
{
  # vs int(sqrt(2))
  require Image::Base::Text;
  my $prev = 0;
  my $diff_total = 0;
  my $diff_count = 0;
  my $prev_count = 0;
  my $prev_sq = 0;
  foreach my $r (1 .. 300) {
    my $count = image_count($r) / 4;
    my $dcount = $count - $prev_count - 1;
    my $sq = int(sqrt(2) * ($r+3));
    my $dsq = $sq - $prev_sq - 1;
    my $star = ($dsq != $dcount ? "***" : "");
    printf "%2d  %3d %3d  %s\n", $r, $dcount,$dsq, $star;
    $prev_count = $count;
    $prev_sq = $sq;
  }
  exit 0;
}

{
  # vs int(sqrt(2))
  my $prev = 0;
  my $diff_total = 0;
  my $diff_count = 0;
  foreach my $r (1 .. 500) {
    my $count = image_count($r);
    my $sq = 4*int(sqrt(2) * ($r+1));
    my $star = ($sq != $count ? "***" : "");
    printf "%2d  %3d %3d  %s\n", $r, $count,$sq, $star;
  }
  exit 0;
}




my $width = 79;
my $height = 23;

my @rows;
my @x;
my @y;
foreach my $r (0 .. 39) {
  my $rr = $r * $r;
  # E(x,y) = x^2*r^2 + y^2*r^2 - r^2*r^2
  #
  # Initially,
  #     d1 = E(x-1/2,y+1)
  #        = (x-1/2)^2*r^2 + (y+1)^2*r^2 - r^2*r^2
  # which for x=r,y=0 is
  #        = r^2 - r^2*r + r^2/4
  #        = (r + 5/4) * r^2
  #
  my $x = $r;
  my $y = 0;
  my $d = ($x-.5)**2 * $rr + ($y+1)**2 * $rr - $rr*$rr;
  my $count = 0;
  while ($x >= $y) {
    ### at: "$x,$y"
    ### assert: $d == ($x-.5)**2 * $rr + ($y+1)**2 * $rr - $rr*$rr

    push @x, $x;
    push @y, $y;
    $rows[$y]->[$x] = ($r%10);
    $count++;

    if( $d < 0 ) {
      $d += $rr * (2*$y + 3);
      ++$y;
    }
    else {
      $d += $rr * (2*$y - 2*$x + 5);
      ++$y;
      --$x;
    }
  }
  my $c = int (2*3.14159*$r/8 + .5);
  printf "%2d %2d %2d  %s\n", $r, $count, $c, ($count!=$c ? "**" : "");
}

foreach my $row (reverse @rows) {
  if ($row) {
    foreach my $char (@$row) {
      print ' ', $char // ' ';
    }
  }
  print "\n";
}


{
  require Math::PlanePath::PixelRings;
  my $path = Math::PlanePath::PixelRings->new (wider => 0,
                                               # step => 0,
                                              );
  ### range: $path->rect_to_n_range (0,0, 0,0)
  exit 0;
}

{
  # search OEIS
  require Image::Base::Text;
  my @count4;
  my @count;
  my @diffs4;
  my @diffs;
  my @diffs0;
  my $prev_count = 0;
  foreach my $r (1 .. 50) {
    my $count = image_count($r);
    push @count4, $count;
    push @count, $count/4;
    my $diff = $count - $prev_count;
    push @diffs4, $diff;
    push @diffs, $diff/4;
    push @diffs0, $diff/4 - 1;
    $prev_count = $count;
  }
  print "count4: ", join(',', @count4), "\n";
  print "count:  ", join(',', @count), "\n";
  print "diffs4: ", join(',', @diffs4), "\n";
  print "diffs:  ", join(',', @diffs), "\n";
  print "diffs0: ", join(',', @diffs0), "\n";
  exit 0;
}

sub image_count {
  my ($r) = @_;
  my $w = 2*$r+1;
  require Image::Base::Text;
  my $image = Image::Base::Text->new (-width => $w,
                                      -height => $w);
  $image->ellipse (0,0, $w-1,$w-1, 'x');
  my $str = $image->save_string;
  my $count = ($str =~ tr/x/x/);
  return $count;
}