#!/usr/bin/perl -w
# Copyright 2012, 2013, 2016 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.004;
use strict;
use Test;
plan tests => 7;
use Math::BigInt try => 'GMP';
use lib 't','xt';
use MyTestHelpers;
BEGIN { MyTestHelpers::nowarnings(); }
use MyOEIS;
# uncomment this to run the ### lines
# use Smart::Comments '###';
use Math::PlanePath::ComplexMinus;
my $path = Math::PlanePath::ComplexMinus->new;
sub is_string_palindrome {
my ($str) = @_;
return $str eq reverse($str);
}
ok (!! is_string_palindrome('acbca'), 1);
ok (! is_string_palindrome('aab'), 1);
sub is_binary_palindrome {
my ($n) = @_;
return is_string_palindrome(sprintf '%b', $n);
}
ok (!! is_binary_palindrome(oct('0b1011101')), 1);
ok (! is_binary_palindrome(oct('0b1011')), 1);
sub binary_reverse {
my ($n) = @_;
$n = substr(Math::BigInt->new($n)->as_bin, 2);
$n = reverse $n;
return Math::BigInt->from_bin($n);
}
### rev: binary_reverse(13).""
ok (binary_reverse(13) == 11, 1);
sub reverse_add_step {
my ($n) = @_;
my ($x1,$y1) = $path->n_to_xy ($n);
my ($x2,$y2) = $path->n_to_xy (binary_reverse($n));
return $path->xy_to_n ($x1+$x2, $y1+$y2);
}
sub reverse_add_palindrome_steps {
my ($n) = @_;
### reverse_add_palindrome_steps(): "$n"
my %seen;
my $count = 0;
my $limit = ($n*0+1) << 50;
while ($n < $limit && !$seen{$n}++) {
### at: "$n ".$n->as_bin
if (is_binary_palindrome($n)) {
### palindrome, count: $count
return $count;
}
$n = reverse_add_step($n);
$count++;
}
return -1;
}
sub reverse_subtract_step {
my ($n, $order) = @_;
my ($x1,$y1) = $path->n_to_xy ($n);
my ($x2,$y2) = $path->n_to_xy (binary_reverse($n));
if ($order) {
($x1,$y1, $x2,$y2) = ($x2,$y2, $x1,$y1);
}
return $path->xy_to_n ($x1-$x2, $y1-$y2);
}
sub reverse_subtract_palindrome_steps {
my ($n, $order) = @_;
### reverse_subtract_palindrome_steps(): "$n"
my %seen;
my $count = 0;
my $limit = ($n*0+1) << 50;
while ($n < $limit && !$seen{$n}++) {
### at: "$n ".$n->as_bin
if ($n==0) {
### zero, count: $count
return $count;
}
$n = reverse_subtract_step($n,$order);
$count++;
}
return -1;
}
#------------------------------------------------------------------------------
# A193306 reverse-subtract steps to 0 (plain-rev)
# A193307 reverse-subtract steps to 0 (rev-plain)
MyOEIS::compare_values
(anum => 'A193306',
max_count => 100,
func => sub {
my ($count) = @_;
my @got;
for (my $n = Math::BigInt->new(0); @got < $count; $n++) {
push @got, reverse_subtract_palindrome_steps($n, 0);
}
return \@got;
});
MyOEIS::compare_values
(anum => 'A193307',
max_count => 100,
func => sub {
my ($count) = @_;
my @got;
for (my $n = Math::BigInt->new(0); @got < $count; $n++) {
push @got, reverse_subtract_palindrome_steps($n, 1);
}
return \@got;
});
#------------------------------------------------------------------------------
# A193241 reverse-add trajectory of binary 10110, in binary
MyOEIS::compare_values
(anum => 'A193241',
func => sub {
my ($count) = @_;
my @got;
my $n = Math::BigInt->new(20);
while (@got < $count) {
push @got, substr($n->as_bin, 2);
$n = reverse_add_step($n);
}
return \@got;
});
# A193240 reverse-add trajectory of binary 110, in binary
MyOEIS::compare_values
(anum => 'A193240',
func => sub {
my ($count) = @_;
my @got;
my $n = Math::BigInt->new(6);
while (@got < $count) {
push @got, substr($n->as_bin, 2);
$n = reverse_add_step($n);
}
return \@got;
});
# A193239 reverse-add steps to palindrome
MyOEIS::compare_values
(anum => 'A193239',
func => sub {
my ($count) = @_;
my @got;
for (my $n = Math::BigInt->new(0); @got < $count; $n++) {
push @got, reverse_add_palindrome_steps($n);
}
return \@got;
});
#------------------------------------------------------------------------------
# A256441 N on negative X axis, X<=0
MyOEIS::compare_values
(anum => 'A256441',
func => sub {
my ($count) = @_;
my @got;
for (my $x = 0; @got < $count; $x++) {
push @got, $path->xy_to_n (-$x,0);
}
return \@got;
});
#------------------------------------------------------------------------------
# A066321 N on X axis, being the base i-1 positive reals
MyOEIS::compare_values
(anum => 'A066321',
func => sub {
my ($count) = @_;
my @got;
for (my $x = 0; @got < $count; $x++) {
push @got, $path->xy_to_n ($x,0);
}
return \@got;
});
# A271472 and in binary
MyOEIS::compare_values
(anum => 'A271472',
func => sub {
my ($count) = @_;
my @got;
for (my $x = 0; @got < $count; $x++) {
push @got, sprintf '%b', $path->xy_to_n ($x,0);
}
return \@got;
});
#------------------------------------------------------------------------------
# A137426 - dX/2 at N=2^(k+2)-1, for k>=0
MyOEIS::compare_values
(anum => 'A137426',
func => sub {
my ($count) = @_;
my @got;
for (my $k = 0; @got < $count; $k++) {
my ($dx,$dy) = $path->n_to_dxdy (Math::BigInt->new(2)**($k+2) - 1);
push @got, $dx/2;
}
return \@got;
});
# A137426 - dY at N=2^k-1, for k>=0
MyOEIS::compare_values
(anum => 'A137426',
func => sub {
my ($count) = @_;
my @got;
for (my $k = 0; @got < $count; $k++) {
my ($dx,$dy) = $path->n_to_dxdy (Math::BigInt->new(2)**$k - 1);
push @got, $dy;
}
return \@got;
});
# GP-Test my(k=0); 2^k-1 == 0
# GP-Test my(k=1); 2^k-1 == 1
# GP-Test my(k=2); 2^k-1 == 3
#------------------------------------------------------------------------------
# A052537 length A,B or C
# A003476 total boundary length / 2
# A203175 boundary length
MyOEIS::compare_values
(anum => 'A203175',
name => 'boundary length',
func => sub {
my ($count) = @_;
my @got = (1,1,2);
my $a = Math::BigInt->new(2);
my $b = Math::BigInt->new(2);
my $c = Math::BigInt->new(0);
while (@got < $count) {
push @got, ($a+$b+$c);
($a,$b,$c) = abc_step($a,$b,$c);
}
return \@got;
});
MyOEIS::compare_values
(anum => 'A003476',
name => 'boundary length / 2',
func => sub {
my ($count) = @_;
my @got = (1);
my $a = Math::BigInt->new(2);
my $b = Math::BigInt->new(2);
my $c = Math::BigInt->new(0);
while (@got < $count) {
push @got, ($a+$b+$c)/2;
($a,$b,$c) = abc_step($a,$b,$c);
}
return \@got;
});
MyOEIS::compare_values
(anum => 'A052537',
func => sub {
my ($count) = @_;
my @got = (1,0);
for (my $i = 0; @got < $count; $i++) {
my ($a,$b,$c) = abc_by_pow($i);
push @got, $c;
}
return \@got;
});
sub abc_step {
my ($a,$b,$c) = @_;
return ($a + 2*$c,
$a,
$b);
}
sub abc_by_pow {
my ($k) = @_;
my $zero = $k*0;
my $r = 1;
my $a = $zero + 2*$r;
my $b = $zero + 2;
my $c = $zero + 2*(1-$r);
foreach (1 .. $k) {
($a,$b,$c) = ((2*$r-1)*$a + 0 + 2*$r*$c,
($r*$r-2*$r+2)*$a + 0 + ($r-1)*($r-1)*$c,
0 + $b);
}
return ($a,$b,$c);
}
#------------------------------------------------------------------------------
# A066322 - N on X axis, diffs at 16k+3,16k+4
MyOEIS::compare_values
(anum => 'A066322',
func => sub {
my ($count) = @_;
my @got;
for (my $i = 0; @got < $count; $i++) {
my $x = 16*$i+3;
my $x_next = 16*$i+4;
my $n = $path->xy_to_n ($x,0);
my $n_next = $path->xy_to_n ($x_next,0);
push @got, $n_next - $n;
}
return \@got;
});
#------------------------------------------------------------------------------
# A066323 - N on X axis, count 1 bits
MyOEIS::compare_values
(anum => 'A066323',
func => sub {
my ($count) = @_;
my @got = (0);
for (my $x = 1; @got < $count; $x++) {
my $n = $path->xy_to_n ($x,0);
push @got, count_1_bits($n);
}
return \@got;
});
sub count_1_bits {
my ($n) = @_;
my $count = 0;
while ($n) {
$count += ($n & 1);
$n >>= 1;
}
return $count;
}
#------------------------------------------------------------------------------
exit 0;