#!/usr/bin/perl -w
# Copyright 2011, 2012, 2018 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 .
use 5.004;
use strict;
use Math::PlanePath::SierpinskiArrowhead;
# uncomment this to run the ### lines
use Smart::Comments;
{
# turn
# A189706 = ternary lowest non-1 and its position
# A189707 positions of 0s, A189708 positions of 1s
# A156595 = ternary lowest non-2 and its position
# GP-DEFINE select_first_n(f,n) = {
# GP-DEFINE my(l=List([]), i=0);
# GP-DEFINE while(#l sub {
require MyFLAT;
require FLAT::Regex;
return FLAT::Regex->new ('((0|1|2)* 0 | []) 1(11)* | (0|1|2)* 2(11)*')->as_dfa
->MyFLAT::minimize
->MyFLAT::set_name("A189707_ternary0");
};
use constant::defer A189708_ternary_flat => sub {
require MyFLAT;
require FLAT::Regex;
return FLAT::Regex->new ('((0|1|2)* 0 | []) (11)* | (0|1|2)* 2 1(11)*')->as_dfa
->MyFLAT::minimize
->MyFLAT::set_name("A189708_ternary0");
};
use constant::defer ternary_any_flat => sub {
require MyFLAT;
require FLAT::Regex;
return FLAT::Regex->new ('(0|1|2)*')->as_dfa
->MyFLAT::minimize
->MyFLAT::set_name("ternary any");
};
A189707_ternary_flat()->union(A189708_ternary_flat())->as_dfa
->equals(ternary_any_flat()) or die;
# MyFLAT::FLAT_show_breadth(A189707_ternary_flat(),3);
# MyFLAT::FLAT_show_breadth(A189708_ternary_flat(),3);
# A189708_ternary_flat()->MyFLAT::reverse->MyFLAT::minimize->MyFLAT::view;
# left = even+even or odd+odd
my $f = FLAT::Regex->new ('(0|2)* (1 (0|2)* 1 (0|2)*)* (1|2) (00)*
| (0|2)* 1 (0|2)* (1 (0|2)* 1 (0|2)*)* (1|2) 0(00)*
')->as_dfa
->MyFLAT::minimize;
$f->MyFLAT::view;
$f->MyFLAT::reverse->MyFLAT::minimize->MyFLAT::view;
require Math::NumSeq::PlanePathTurn;
require Math::BaseCnv;
my $seq = Math::NumSeq::PlanePathTurn->new
(planepath => 'SierpinskiArrowhead',
turn_type => 'Left');
foreach (1 .. 400) {
my ($i, $value) = $seq->next;
my $i3 = Math::BaseCnv::cnv($i,10,3);
my $calc = $f->contains($i3) ? 1 : 0;
my $diff = ($value == $calc ? "" : " ***");
print "$i $i3 $value $calc$diff\n";
}
exit 0;
}
{
# turn sequence
require Math::NumSeq::PlanePathTurn;
require Math::BaseCnv;
my $seq = Math::NumSeq::PlanePathTurn->new
(planepath => 'SierpinskiArrowhead',
turn_type => 'Left');
foreach (1 .. 400) {
my ($i, $value) = $seq->next;
my $i3 = Math::BaseCnv::cnv($i,10,3);
# my $calc = calc_turnleft($i);
my $calc = WORKING__calc_turnleft($i);
my $diff = ($value == $calc ? "" : " ***");
print "$i $i3 $value $calc$diff\n";
}
sub calc_turnleft { # not working
my ($n) = @_;
my $ret = 1;
my $flip = 0;
while ($n && ($n % 9) == 0) {
$n = int($n/9);
}
if ($n) {
my $digit = $n % 9;
my $flip = ($digit == 0
|| $digit == 1 # 01
# || $digit == 3 # 10
|| $digit == 5 # 12
|| $digit == 6 # 20
|| $digit == 7 # 21
);
$ret ^= $flip;
$n = int($n/9);
}
while ($n) {
my $digit = $n % 9;
my $flip = ($digit == 1 # 01
|| $digit == 3 # 10
|| $digit == 5 # 12
|| $digit == 7 # 21
);
$ret ^= $flip;
$n = int($n/9);
}
return $ret;
}
# GP-DEFINE CountLowZeros(n) = valuation(n,3);
# vector(20,n, CountLowZeros(n))
# GP-DEFINE CountLowTwos(n) = my(ret=0); while(n%3==2, n\=3;ret++); ret;
# GP-DEFINE CountLowOnes(n) = my(ret=0); while(n%3==1, n\=3;ret++); ret;
# GP-DEFINE CountOnes(n) = vecsum(apply(d->d==1,digits(n,3)));
# vector(20,n,n--; CountOnes(n))
# GP-DEFINE LowestNonZero(n) = {
# GP-DEFINE if(n<1,error("LowestNonZero() is for n>=1")); \
# GP-DEFINE (n / 3^valuation(n,3)) % 3;
# GP-DEFINE }
# GP-DEFINE LowestNonOne(n) = while((n%3)==1,n=n\3); n%3;
# GP-DEFINE LowestNonTwo(n) = while((n%3)==2,n=n\3); n%3;
# GP-DEFINE CountOnesExceptLowestNonZero(n) = {
# GP-DEFINE while(n && n%3==0, n/=3);
# GP-DEFINE CountOnes(n\3);
# GP-DEFINE }
# vector(20,n,n--; CountOnes(n))
# GP-DEFINE turn_left(n) = ! turn_right(n);
# GP-DEFINE turn_right(n) = (CountOnes(n) + LowestNonZero(n) + CountLowZeros(n)) % 2;
# GP-DEFINE turn_right(n) = (CountOnesExceptLowestNonZero(n) + CountLowZeros(n)) % 2;
# vector(20,n, turn_left(n))
# vector(22,n, turn_right(n))
# vector(15,n, turn_left(n)-turn_right(n))
# not in OEIS: 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1
# not in OEIS: 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,1,1
# not in OEIS: 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1
# at odd and even positions
# vector(15,n, turn_left(2*n)-turn_right(2*n))
# vector(18,n, turn_left(2*n-1)-turn_right(2*n-1))
# not in OEIS: 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1
# not in OEIS: 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1
# GP-Test vector(1000,m,m--; ((LowestNonOne(m)==0)+CountLowOnes(m))%2) == \
# GP-Test vector(1000,m, turn_left(2*m-1))
# GP-Test vector(1000,m,m--; ((LowestNonOne(m)==2)+CountLowOnes(m))%2) == \
# GP-Test vector(1000,m,m--; turn_right(2*m+1))
# GP-Test vector(1000,m,m--; ((LowestNonTwo(m)==0)+CountLowTwos(m))%2) == \
# GP-Test vector(1000,m, turn_left(2*m))
# GP-Test vector(1000,m,m--; (LowestNonTwo(m)+CountLowTwos(m))%2) == \
# GP-Test vector(1000,m, turn_right(2*m))
# GP-Test vector(1000,m, (LowestNonZero(m)+CountLowZeros(m))%2) == \
# GP-Test vector(1000,m, turn_left(2*m))
# GP-Test vector(1000,n, (n + LowestNonZero(n) + CountLowZeros(n))%2) == \
# GP-Test vector(1000,n, turn_right(n))
# vector(25,n, (1+LowestNonZero(n) + CountLowZeros(n))%2)
# is A189706 with index change low-2s -> low-0s
# ternary
# [ count 1 digits ] [1 or 2] [ count low 0 digits ]
# vector(10,k, (3^k)%2)
# vector(10,k, (2*3^k)%2)
sub WORKING__calc_turnleft { # works
my ($n) = @_;
my $ret = 1;
while ($n && ($n % 3) == 0) {
$ret ^= 1; # flip for trailing 0s
$n = int($n/3);
}
$n = int($n/3); # skip lowest non-0
while ($n) {
if (($n % 3) == 1) { # flip for all 1s
$ret ^= 1;
}
$n = int($n/3);
}
return $ret;
}
sub count_digits {
my ($n) = @_;
my $count = 0;
while ($n) {
$count++;
$n = int($n/3);
}
return $count;
}
sub count_1_digits {
my ($n) = @_;
my $count = 0;
while ($n) {
$count += (($n % 3) == 1);
$n = int($n/3);
}
return $count;
}
exit 0;
}
{
# direction sequence
# 9-17 = mirror image horizontally 3-dir
# 18-26 = dir+2
require Math::NumSeq::PlanePathDelta;
require Math::BaseCnv;
my $seq = Math::NumSeq::PlanePathDelta->new
(planepath => 'SierpinskiArrowhead',
delta_type => 'TDir6');
foreach (1 .. 3**4+1) {
my ($i, $value) = $seq->next;
# $value %= 6;
my $i3 = Math::BaseCnv::cnv($i,10,3);
my $calc = calc_dir6($i);
print "$i $i3 $value $calc\n";
}
sub calc_dir6 { # works
my ($n) = @_;
my $dir = 1;
while ($n) {
if (($n % 9) == 0) {
} elsif (($n % 9) == 1) {
$dir = 3 - $dir;
} elsif (($n % 9) == 2) {
$dir = $dir + 2;
} elsif (($n % 9) == 3) {
$dir = 3 - $dir;
} elsif (($n % 9) == 4) {
} elsif (($n % 9) == 5) {
$dir = 1 - $dir;
} elsif (($n % 9) == 6) {
$dir = $dir - 2;
} elsif (($n % 9) == 7) {
$dir = 1 - $dir;
} elsif (($n % 9) == 8) {
}
$n = int($n/9);
}
return $dir % 6;
}
sub Xcalc_dir6 { # works
my ($n) = @_;
my $dir = 1;
while ($n) {
if (($n % 3) == 0) {
}
if (($n % 3) == 1) {
# mirror
$dir = 3 - $dir;
}
if (($n % 3) == 2) {
$dir = $dir + 2;
}
$n = int($n/3);
if (($n % 3) == 0) {
}
if (($n % 3) == 1) {
# mirror
$dir = 3 - $dir;
}
if (($n % 3) == 2) {
$dir = $dir - 2;
}
$n = int($n/3);
}
return $dir % 6;
}
exit 0;
}