Math-PlanePath-Toothpick

 view release on metacpan or  search on metacpan

devel/toothpick.pl  view on Meta::CPAN


{
  # tree_depth_to_n() octant
  # d=2  n=2           1
  # d=6  n=8         100
  # d=14 n=28      11100
  # d=30 n=100   1100100
  # d=62 n=372 101110100
  # oct(2^(k+1)) = 4*oct(2^k)  base,extend,upper,lower
  #              + 2           middle two unvisited
  #              - (2^k - 2)   unduplicate upper,lower diagonal
  #   = 4*oct(2^k) + 4 - 2^k
  # oct(2^k)
  #   = 4 - 2^(k-1) + 4*oct(2^(k-1))
  #   = 4 - 2^(k-1) + 4*(4 - 2^(k-2) + oct(2^(k-2)))
  #   = 4 - 2^(k-1) + 4*(4 - 2^(k-2) + 4*(4 - 2^(k-3) + 4*oct(2^(k-3))))
  # 4*(1 + 4 + 16 + ... + 4^(k-2))
  #   = 4*(4^(k-1) - 1)/3
  # 2^(k-1) + 4*2^(k-2) + 16*2^(k-3) + ... + 4^(k-1)*1
  #   = 2^(k-1) + 2^(k+0) + 2^(k+1) + ... + 2^(2k-2)
  #   = 2^(k-1)*(1 + 2 + 4 + ... + 2^(k-2))
  #   = 2^(k-1) * (2^(k-1) - 1)
  #
  # k=2;  (4 - 2^1 + 0) = 2
  # k=3; 4 - 2^2 + 4*(4 - 2^1 + 0) = 8
  # k=4; 4 - 2^3 + 4*(4 - 2^2 + 4*(4 - 2^1 + 0)) = 28
  #      = 4 + 4*(4 + 4*(4))  - 2^3 + 4*(-2^2 + 4*(-2^1))
  #
  # oct(2^k) = 4*(4^(k-1) - 1)/3 - 2^(k-1)*(2^(k-1)-1)
  #          = (4*(4^(k-1) - 1) - 3*2^(k-1)*(2^(k-1)-1) ) / 3
  #          = (4*4^(k-1) - 4 - 3*4^(k-1) + 3*2^(k-1) ) / 3
  #          = (4^(k-1) - 4 + 3*2^(k-1) ) / 3
  #          = (4^(k-1) - 4)/3 + 2^(k-1)
  #          = (4^k - 16)/12 + 2^(k-1)
  # pow = 2^(k-1)
  # oct(2*pow) = (pow*pow + 3*pow - 4)/3
  # oct(pow) = (pow*(pow + 3) - 4)/3
  #
  # oct(pow+rem) = oct(pow) + 2*oct(rem) + oct(rem+1) - rem + 4
  # oct(36) = oct(32) + 2*oct(4) + oct(5) - 4 + 4    want 107
  #           100     + 2*2      + 3 - 4 + 4
  #
  # oct(pow + pow-1)
  #   = oct(pow) + 2*oct(pow-1) + oct(pow) - (pow-1) + 4
  #   = 2*oct(pow) - (pow-1) + 4 + 2*oct(pow-1)
  #   = 2*oct(2^(k-1)) + 4*oct(2^(k-1)) + 8*oct(2^(k-1)) + ... + 2^(k-1)*oct(2)
  #     + 2^(k-1) - 1 + 2^(k-2) - 1 + ... + 2^1 - 1
  #     + 2^(k-1) * oct(3)
  #
  # 2^(k-1) - 1 + 2^(k-2) - 1 + ... + 2^1 - 1
  #   = 2^k - 1 - k
  #
  require Math::PlanePath::ToothpickTreeByCells;
  require Math::BaseCnv;
  my $cells = Math::PlanePath::ToothpickTreeByCells->new (parts => 'octant');
  my $path = Math::PlanePath::ToothpickTree->new (parts => 'octant');
  for (my $depth = 2; $depth <= 36; $depth++) {
    my $depth = $depth-2;
    my $n = $cells->tree_depth_to_n($depth);
    my $n2 = Math::BaseCnv::cnv($n,10,2);
    my $f = oct_pow_by_formula($depth);
    my $p = $path->tree_depth_to_n($depth);
    my $diff = ($p == $n ? '' : '***');
    my $d2 = $depth + 2;
    if (is_pow2($d2)) { print "\n"; }
    print "$depth  $d2  n=$n  $n2  p=$p$diff   f=$f\n";
  }

  sub oct_pow_by_formula {
    my ($depth) = @_;
    $depth += 2;  # parts=4 basis
    if ($depth <= 2) { return 0; }
    if ($depth == 4) { return 2; }
    $depth /= 2;
    return (4*oct_pow_by_formula($depth-2)
            + 4
            - $depth
           );
  }
  sub is_pow2 {
    my ($n) = @_;
    while ($n > 1) {
      if ($n & 1) {
        return 0;
      }
      $n >>= 1;
    }
    return ($n == 1);
  }
  exit 0;
}
{
  # tree_n_to_depth()
  require Math::PlanePath::ToothpickTreeByCells;
  my $path = Math::PlanePath::ToothpickTreeByCells->new (parts => 'octant');
  my $prev = -999;
  my $count = 0;
  my $total = 0;
  for (my $n = 2; $n <= 256; $n *= 2) {
    my $depth = $path->tree_n_to_depth($n);
    if ($depth != $prev) {
      print "$depth n=$n  added=$count  $total\n";
      $count = 0;
      $prev = $depth;
    }
    $count++;
    $total++;
  }
  exit 0;
}

{
  # ascii art with toothpick lines

  require Image::Base::Text;

  my $run = sub {
    my ($path, $n_hi) = @_;

    my $width = 78;
    my $height = 40;
    my $x_lo = -$width/2;
    my $y_lo = -$height/2;

    my $x_hi = $x_lo + $width - 1;
    my $y_hi = $y_lo + $height - 1;
    my $image = Image::Base::Text->new (-width => $width,
                                        -height => $height);
    my $plot = sub {
      my ($x,$y,$char) = @_;
      $x -= $x_lo;
      $y -= $y_lo;
      return if $x < 0 || $y < 0 || $x >= $width || $y >= $height;
      $image->xy ($x,$height-1-$y,$char);
    };



( run in 1.370 second using v1.01-cache-2.11-cpan-39bf76dae61 )