September Morn Update

This commit is contained in:
Ingy döt Net 2019-09-12 10:33:56 -07:00
parent 4e2d22a71d
commit aac6731f2c
6856 changed files with 141342 additions and 21127 deletions

View file

@ -1,239 +1,254 @@
import extensions.
import extensions;
const dig = ("00","01","10").
const dig1 = ("","1","10").
const dig = new string[]{"00","01","10"};
const dig1 = new string[]{"","1","10"};
sealed struct ZeckendorfNumber :: BaseNumber
sealed struct ZeckendorfNumber
{
int dVal.
int dLen.
int dVal;
int dLen;
clone
= ZeckendorfNumber $new(dVal,dLen).
clone()
= ZeckendorfNumber.newInternal(dVal,dLen);
stacksafe explicit n(LiteralValue s)
[
int i := s length - 1.
int q := 1.
cast n(string s)
{
int i := s.Length - 1;
int q := 1;
dLen := i / 2.
dVal := 0.
dLen := i / 2;
dVal := 0;
while (i >= 0)
[
dVal += ((intConvertor convert(s[i]) - 48) * q).
q *= 2.
{
dVal += ((intConvertor.convert(s[i]) - 48) * q);
q *= 2;
i -= 1.
].
]
i -= 1
}
}
stacksafe $readContent vint:val vint:len
[
val int := dVal.
len int := dLen.
]
internal readContent(ref int val, ref int len)
{
val := dVal;
len := dLen;
}
sealed $a(IntNumber n)
[
int i := n.
private a(int n)
{
int i := n;
while (true)
[
{
if (dLen < i)
[
dLen := i.
].
{
dLen := i
};
((dVal >> (i * 2)) && 3) =>
0 [ ^ $self ];
1 [ ^ $self ];
2 [
ifnot ((dVal >> ((i + 1) * 2)) allMask:1)
[
^ $self.
].
int v2 := dVal $shr (i * 2);
int v := (dVal $shr (i * 2)) && 3;
dVal += (1 << (i*2 + 1)).
^ $self.
];
3 [
dVal := dVal && ((3 << i*2) inverted).
((dVal $shr (i * 2)) && 3) =>
0 { ^ self }
1 { ^ self }
2 {
ifnot ((dVal $shr ((i + 1) * 2)).allMask:1)
{
^ self
};
$self $b((i+1)*2).
].
dVal += (1 $shl (i*2 + 1));
i += 1.
].
]
^ self
}
3 {
int tmp := 3 $shl (i * 2);
tmp := tmp.xor(-1);
dVal := dVal && tmp;
inc
[
dVal += 1.
$self $a(0).
]
self.b((i+1)*2)
};
$b(IntNumber pos)
[
if (pos == 0) [ ^ $self inc ].
i += 1
}
}
ifnot((dVal >> pos) allMask:1)
[
dVal += (1 << pos).
$self $a(pos / 2).
if (pos > 1) [ $self $a((pos / 2) - 1) ]
];
[
dVal := dVal && (1 << pos) inverted.
$self $b(pos + 1).
$self $b(pos - (pos > 1) iif(2,1)).
].
]
inc()
{
dVal += 1;
self.a(0)
}
$c(IntNumber pos)
[
if ((dVal >> pos) allMask:1)
[
dVal := dVal && (1 << pos) inverted.
private b(int pos)
{
if (pos == 0) { ^ self.inc() };
^ $self
].
ifnot((dVal $shr pos).allMask:1)
{
dVal += (1 $shl pos);
self.a(pos / 2);
if (pos > 1) { self.a((pos / 2) - 1) }
}
else
{
dVal := dVal && (1 $shl pos).Inverted;
self.b(pos + 1);
int arg := pos - ((pos > 1) ? 2 : 1);
self.b(/*pos - ((pos > 1) ? 2 : 1)*/arg)
}
}
$self $c(pos + 1).
private c(int pos)
{
if ((dVal $shr pos).allMask:1)
{
int tmp := 1 $shl pos;
tmp := tmp.xor(-1);
dVal := dVal && tmp;
^ self
};
self.c(pos + 1);
if (pos > 0)
[
$self $b(pos - 1).
];
[
$self inc.
]
]
{
self.b(pos - 1)
}
else
{
self.inc()
}
}
constructor $sum(ZeckendorfNumber n, ZeckendorfNumber m)
[
int mVal := 0.
int mLen := 0.
internal constructor sum(ZeckendorfNumber n, ZeckendorfNumber m)
{
int mVal := 0;
int mLen := 0;
n $readContent vint:dVal vint:dLen.
m $readContent vint:mVal vint:mLen.
n.readContent(ref dVal, ref dLen);
m.readContent(ref mVal, ref mLen);
0 till((mLen + 1) * 2) do(:GN)
[
if (mVal shiftRight:GN; allMask:1)
[
$self $b(GN).
].
].
]
for(int GN := 0, GN < (mLen + 1) * 2, GN += 1)
{
if ((mVal $shr GN).allMask:1)
{
self.b(GN)
}
}
}
constructor $difference(ZeckendorfNumber n, ZeckendorfNumber m)
[
int mVal := 0.
int mLen := 0.
internal constructor difference(ZeckendorfNumber n, ZeckendorfNumber m)
{
int mVal := 0;
int mLen := 0;
n $readContent vint:dVal vint:dLen.
m $readContent vint:mVal vint:mLen.
n.readContent(ref dVal, ref dLen);
m.readContent(ref mVal, ref mLen);
0 till((mLen + 1) * 2) do(:GN)
[
if (mVal shiftRight:GN; allMask:1)
[
$self $c(GN).
].
].
for(int GN := 0, GN < (mLen + 1) * 2, GN += 1)
{
if ((mVal $shr GN).allMask:1)
{
self.c(GN)
}
};
while ((((dVal >> (dLen*2)) && 3) == 0) || (dLen == 0))
[
dLen -= 1.
].
]
while (((dVal $shr (dLen*2)) && 3) == 0 || dLen == 0)
{
dLen -= 1
}
}
constructor $product(ZeckendorfNumber n, ZeckendorfNumber m)
[
n $readContent vint:dVal vint:dLen.
internal constructor product(ZeckendorfNumber n, ZeckendorfNumber m)
{
n.readContent(ref dVal, ref dLen);
var Na := m.
var Nb := m.
var Nr := 0n.
var Nt := 0n.
ZeckendorfNumber Na := m;
ZeckendorfNumber Nb := m;
ZeckendorfNumber Nr := 0n;
ZeckendorfNumber Nt := 0n;
0 to((dLen + 1) * 2) do(:i)
[
if (((dVal shiftRight:i) && 1) > 0)
[
for(int i := 0, i < (dLen + 1) * 2, i += 1)
{
if (((dVal $shr i) && 1) > 0)
{
Nr += Nb
].
Nt := Nb.
Nb += Na.
Na := Nt.
].
};
Nt := Nb;
Nb += Na;
Na := Nt
};
Nr $readContent vint:dVal vint:dLen.
]
Nr.readContent(ref dVal, ref dLen);
}
constructor $new(IntNumber v, IntNumber l)
[
dVal := v.
dLen := l.
]
internal constructor newInternal(int v, int l)
{
dVal := v;
dLen := l
}
literal
[
get string Printable()
{
if (dVal == 0)
[ ^ "0". ].
{ ^ "0" };
literal s := dig1[(dVal >> (dLen * 2)) && 3].
int i := dLen - 1.
//int n := dVal $shr (dLen * 2);
//int r := (dVal $shr (dLen * 2)) && 3;
string s := dig1[(dVal $shr (dLen * 2)) && 3];
int i := dLen - 1;
while (i >= 0)
[
s := s + dig[(dVal >> (i * 2)) && 3].
{
s := s + dig[(dVal $shr (i * 2)) && 3];
i-=1
].
};
^ s.
]
^ s
}
add(ZeckendorfNumber n)
= ZeckendorfNumber $sum($self, n).
= ZeckendorfNumber.sum(self, n);
subtract(ZeckendorfNumber n)
= ZeckendorfNumber $difference($self, n).
= ZeckendorfNumber.difference(self, n);
multiply(ZeckendorfNumber n)
= ZeckendorfNumber $product($self, n).
= ZeckendorfNumber.product(self, n);
}
program =
[
console printLine("Addition:").
var n := 10n.
public program()
{
console.printLine("Addition:");
var n := 10n;
n += 10n.
console printLine(n).
n += 10n.
console printLine(n).
n += 1001n.
console printLine(n).
n += 1000n.
console printLine(n).
n += 10101n.
console printLine(n).
n += 10n;
console.printLine(n);
n += 10n;
console.printLine(n);
n += 1001n;
console.printLine(n);
n += 1000n;
console.printLine(n);
n += 10101n;
console.printLine(n);
console printLine("Subtraction:").
n := 1000n.
n -= 101n.
console printLine(n).
n := 10101010n.
n -= 1010101n.
console printLine(n).
console.printLine("Subtraction:");
n := 1000n;
n -= 101n;
console.printLine(n);
n := 10101010n;
n -= 1010101n;
console.printLine(n);
console printLine("Multiplication:").
n := 1001n.
n *= 101n.
console printLine(n).
n := 101010n.
n += 101n.
console printLine(n).
].
console.printLine("Multiplication:");
n := 1001n;
n *= 101n;
console.printLine(n);
n := 101010n;
n += 101n;
console.printLine(n)
}

View file

@ -0,0 +1,184 @@
package main
import (
"fmt"
"strings"
)
var (
dig = [3]string{"00", "01", "10"}
dig1 = [3]string{"", "1", "10"}
)
type Zeckendorf struct{ dVal, dLen int }
func NewZeck(x string) *Zeckendorf {
z := new(Zeckendorf)
if x == "" {
x = "0"
}
q := 1
i := len(x) - 1
z.dLen = i / 2
for ; i >= 0; i-- {
z.dVal += int(x[i]-'0') * q
q *= 2
}
return z
}
func (z *Zeckendorf) a(i int) {
for ; ; i++ {
if z.dLen < i {
z.dLen = i
}
j := (z.dVal >> uint(i*2)) & 3
switch j {
case 0, 1:
return
case 2:
if ((z.dVal >> (uint(i+1) * 2)) & 1) != 1 {
return
}
z.dVal += 1 << uint(i*2+1)
return
case 3:
z.dVal &= ^(3 << uint(i*2))
z.b((i + 1) * 2)
}
}
}
func (z *Zeckendorf) b(pos int) {
if pos == 0 {
z.Inc()
return
}
if ((z.dVal >> uint(pos)) & 1) == 0 {
z.dVal += 1 << uint(pos)
z.a(pos / 2)
if pos > 1 {
z.a(pos/2 - 1)
}
} else {
z.dVal &= ^(1 << uint(pos))
z.b(pos + 1)
temp := 1
if pos > 1 {
temp = 2
}
z.b(pos - temp)
}
}
func (z *Zeckendorf) c(pos int) {
if ((z.dVal >> uint(pos)) & 1) == 1 {
z.dVal &= ^(1 << uint(pos))
return
}
z.c(pos + 1)
if pos > 0 {
z.b(pos - 1)
} else {
z.Inc()
}
}
func (z *Zeckendorf) Inc() {
z.dVal++
z.a(0)
}
func (z1 *Zeckendorf) PlusAssign(z2 *Zeckendorf) {
for gn := 0; gn < (z2.dLen+1)*2; gn++ {
if ((z2.dVal >> uint(gn)) & 1) == 1 {
z1.b(gn)
}
}
}
func (z1 *Zeckendorf) MinusAssign(z2 *Zeckendorf) {
for gn := 0; gn < (z2.dLen+1)*2; gn++ {
if ((z2.dVal >> uint(gn)) & 1) == 1 {
z1.c(gn)
}
}
for z1.dLen > 0 && ((z1.dVal>>uint(z1.dLen*2))&3) == 0 {
z1.dLen--
}
}
func (z1 *Zeckendorf) TimesAssign(z2 *Zeckendorf) {
na := z2.Copy()
nb := z2.Copy()
nr := new(Zeckendorf)
for i := 0; i <= (z1.dLen+1)*2; i++ {
if ((z1.dVal >> uint(i)) & 1) > 0 {
nr.PlusAssign(nb)
}
nt := nb.Copy()
nb.PlusAssign(na)
na = nt.Copy()
}
z1.dVal = nr.dVal
z1.dLen = nr.dLen
}
func (z *Zeckendorf) Copy() *Zeckendorf {
return &Zeckendorf{z.dVal, z.dLen}
}
func (z1 *Zeckendorf) Compare(z2 *Zeckendorf) int {
switch {
case z1.dVal < z2.dVal:
return -1
case z1.dVal > z2.dVal:
return 1
default:
return 0
}
}
func (z *Zeckendorf) String() string {
if z.dVal == 0 {
return "0"
}
var sb strings.Builder
sb.WriteString(dig1[(z.dVal>>uint(z.dLen*2))&3])
for i := z.dLen - 1; i >= 0; i-- {
sb.WriteString(dig[(z.dVal>>uint(i*2))&3])
}
return sb.String()
}
func main() {
fmt.Println("Addition:")
g := NewZeck("10")
g.PlusAssign(NewZeck("10"))
fmt.Println(g)
g.PlusAssign(NewZeck("10"))
fmt.Println(g)
g.PlusAssign(NewZeck("1001"))
fmt.Println(g)
g.PlusAssign(NewZeck("1000"))
fmt.Println(g)
g.PlusAssign(NewZeck("10101"))
fmt.Println(g)
fmt.Println("\nSubtraction:")
g = NewZeck("1000")
g.MinusAssign(NewZeck("101"))
fmt.Println(g)
g = NewZeck("10101010")
g.MinusAssign(NewZeck("1010101"))
fmt.Println(g)
fmt.Println("\nMultiplication:")
g = NewZeck("1001")
g.TimesAssign(NewZeck("101"))
fmt.Println(g)
g = NewZeck("101010")
g.PlusAssign(NewZeck("101"))
fmt.Println(g)
}

View file

@ -0,0 +1,172 @@
import Base.*, Base.+, Base.-, Base./, Base.show, Base.!=, Base.==, Base.<=, Base.<, Base.>, Base.>=, Base.divrem
const z0 = "0"
const z1 = "1"
const flipordered = (z1 < z0)
mutable struct Z s::String end
Z() = Z(z0)
Z(z::Z) = Z(z.s)
pairlen(x::Z, y::Z) = max(length(x.s), length(y.s))
tolen(x::Z, n::Int) = (s = x.s; while length(s) < n s = z0 * s end; s)
<(x::Z, y::Z) = (l = pairlen(x, y); flipordered ? tolen(x, l) > tolen(y, l) : tolen(x, l) < tolen(y, l))
>(x::Z, y::Z) = (l = pairlen(x, y); flipordered ? tolen(x, l) < tolen(y, l) : tolen(x, l) > tolen(y, l))
==(x::Z, y::Z) = (l = pairlen(x, y); tolen(x, l) == tolen(y, l))
<=(x::Z, y::Z) = (l = pairlen(x, y); flipordered ? tolen(x, l) >= tolen(y, l) : tolen(x, l) <= tolen(y, l))
>=(x::Z, y::Z) = (l = pairlen(x, y); flipordered ? tolen(x, l) <= tolen(y, l) : tolen(x, l) >= tolen(y, l))
!=(x::Z, y::Z) = (l = pairlen(x, y); tolen(x, l) != tolen(y, l))
function tocanonical(z::Z)
while occursin(z0 * z1 * z1, z.s)
z.s = replace(z.s, z0 * z1 * z1 => z1 * z0 * z0)
end
len = length(z.s)
if len > 1 && z.s[1:2] == z1 * z1
z.s = z1 * z0 * z0 * ((len > 2) ? z.s[3:end] : "")
end
while (len = length(z.s)) > 1 && string(z.s[1]) == z0
if len == 2
if z.s == z0 * z0
z.s = z0
elseif z.s == z0 * z1
z.s = z1
end
else
z.s = z.s[2:end]
end
end
z
end
function inc(z)
if z.s[end] == z0[1]
z.s = z.s[1:end-1] * z1[1]
elseif z.s[end] == z1[1]
if length(z.s) > 1
if z.s[end-1:end] == z0 * z1
z.s = z.s[1:end-2] * z1 * z0
end
else
z.s = z1 * z0
end
end
tocanonical(z)
end
function dec(z)
if z.s[end] == z1[1]
z.s = z.s[1:end-1] * z0
else
if (m = match(Regex(z1 * z0 * '+' * '$'), z.s)) != nothing
len = length(m.match)
if iseven(len)
z.s = z.s[1:end-len] * (z0 * z1) ^ div(len, 2)
else
z.s = z.s[1:end-len] * (z0 * z1) ^ div(len, 2) * z0
end
end
end
tocanonical(z)
z
end
function +(x::Z, y::Z)
a = Z(x.s)
b = Z(y.s)
while b.s != z0
inc(a)
dec(b)
end
a
end
function -(x::Z, y::Z)
a = Z(x.s)
b = Z(y.s)
while b.s != z0
dec(a)
dec(b)
end
a
end
function *(x::Z, y::Z)
if (x.s == z0) || (y.s == z0)
return Z(z0)
elseif x.s == z1
return Z(y.s)
elseif y.s == z1
return Z(x.s)
end
a = Z(x.s)
b = Z(z1)
while b != y
c = Z(z0)
while c != x
inc(a)
inc(c)
end
inc(b)
end
a
end
function divrem(x::Z, y::Z)
if y.s == z0
throw("Zeckendorf division by 0")
elseif (y.s == z1) || (x.s == z0)
return Z(x.s)
end
a = Z(x.s)
b = Z(y.s)
c = Z(z0)
while a > b
a = a - b
inc(c)
end
tocanonical(c), tocanonical(a)
end
function /(x::Z, y::Z)
a, _ = divrem(x, y)
a
end
show(io::IO, z::Z) = show(io, parse(BigInt, tocanonical(z).s))
function zeckendorftest()
a = Z("10")
b = Z("1001")
c = Z("1000")
d = Z("10101")
println("Addition:")
x = a
println(x += a)
println(x += a)
println(x += b)
println(x += c)
println(x += d)
println("\nSubtraction:")
x = Z("1000")
println(x - Z("101"))
x = Z("10101010")
println(x - Z("1010101"))
println("\nMultiplication:")
x = Z("1001")
y = Z("101")
println(x * y)
println(Z("101010") * y)
println("\nDivision:")
x = Z("1000101")
y = Z("101")
println(x / y)
println(divrem(x, y))
end
zeckendorftest()

View file

@ -17,7 +17,6 @@ sub infix:<eqz>($a, $b) { $a eq $b };
# not equal
sub infix:<nez>($a, $b) { $a ne $b };
######## Operators for Zeckendorf arithmetic ########
# post increment
@ -37,10 +36,10 @@ sub postfix:<--z>($a is rw) {
}
# addition
sub infix:<+z>($a is copy, $b is copy) { $a++z while $b--z nez $z0; $a };
sub infix:<+z>($a is copy, $b is copy) { $a++z; $a++z while $b--z nez $z0; $a };
# subtraction
sub infix:<-z>($a is copy, $b is copy) { $a--z while $b--z nez $z0; $a };
sub infix:<-z>($a is copy, $b is copy) { $a--z; $a--z while $b--z nez $z0; $a };
# multiplication
sub infix:<*z>($a, $b) {
@ -65,13 +64,13 @@ sub infix:</z>($a is copy, $b is copy) {
repeat {
my $d = $b +z ($z1 ~ $z0);
$c++z;
$a++z;
$a--z while $d--z nez $z0
} until $a ltz $b;
$c ~= " remainder $a" if $a nez $z0;
$c
};
###################### Testing ######################
# helper sub to translate constants into the particular glyphs you used

View file

@ -0,0 +1,267 @@
sequence fib = {1,1}
function zeckendorf(atom n)
-- Same as [[Zeckendorf_number_representation#Phix]]
atom r = 0
while fib[$]<n do
fib &= fib[$] + fib[$-1]
end while
integer k = length(fib)
while k>2 and n<fib[k] do
k -= 1
end while
for i=k to 2 by -1 do
integer c = n>=fib[i]
r += r+c
n -= c*fib[i]
end for
return r
end function
function decimal(object z)
-- Convert Zeckendorf number(s) to decimal
atom dec = 0, bit = 2
if sequence(z) then
for i=1 to length(z) do
z[i] = decimal(z[i])
end for
return z
end if
while z do
if and_bits(z,1) then
dec += fib[bit]
end if
bit += 1
if bit>length(fib) then
fib &= fib[$] + fib[$-1]
end if
z = floor(z/2)
end while
return dec
end function
function to_bits(integer x)
-- Simplified copy of int_to_bits(), but in reverse order,
-- and +ve only but (also only) as many bits as needed, and
-- ensures there are *two* trailing 0 (most significant)
sequence bits = {}
if x<0 then ?9/0 end if -- sanity/avoid infinite loop
while 1 do
bits &= remainder(x,2)
if x=0 then exit end if
x = floor(x/2)
end while
bits &= 0 -- (since eg 101+101 -> 10000)
return bits
end function
function to_bits2(integer a,b)
-- Apply to_bits() to a and b, and pad to the same length
sequence sa = to_bits(a), sb = to_bits(b)
integer diff = length(sa)-length(sb)
if diff!=0 then
if diff<0 then sa &= repeat(0,-diff)
else sb &= repeat(0,+diff)
end if
end if
return {sa,sb}
end function
function to_int(sequence bits)
-- Copy of bits_to_int(), but in reverse order (lsb last)
atom val = 0, p = 1
for i=length(bits) to 1 by -1 do
if bits[i] then
val += p
end if
p += p
end for
return val
end function
function zstr(object z)
if sequence(z) then
for i=1 to length(z) do
z[i] = zstr(z[i])
end for
return z
end if
return sprintf("%b",z)
end function
function rep(sequence res, integer ds, sequence was, wth)
-- helper for cleanup, validates replacements
integer de = ds+length(was)-1
if res[ds..de]!=was then ?9/0 end if
if length(was)!=length(wth) then ?9/0 end if
res[ds..de] = wth
return res
end function
function zcleanup(sequence res)
-- (shared by zadd and zsub)
integer l = length(res)
-- first stage, left to right, {020x -> 100x', 030x -> 110x', 021x->110x, 012x->101x}
for i=1 to l-3 do
switch res[i..i+2]
case {0,2,0}: res[i..i+2] = {1,0,0} res[i+3] += 1
case {0,3,0}: res[i..i+2] = {1,1,0} res[i+3] += 1
case {0,2,1}: res[i..i+2] = {1,1,0}
case {0,1,2}: res[i..i+2] = {1,0,1}
end switch
end for
-- first stage cleanup
if l>1 then
if res[l-1]=3 then res = rep(res,l-2,{0,3,0},{1,1,1}) -- 030 -> 111
elsif res[l-1]=2 then
if res[l-2]=0 then res = rep(res,l-2,{0,2,0},{1,0,1}) -- 020 -> 101
else res = rep(res,l-3,{0,1,2,0},{1,0,1,0}) -- 0120 -> 1010
end if
end if
end if
if res[l]=3 then res = rep(res,l-1,{0,3},{1,1}) -- 03 -> 11
elsif res[l]=2 then
if res[l-1]=0 then res = rep(res,l-1,{0,2},{1,0}) -- 02 -> 10
else res = rep(res,l-2,{0,1,2},{1,0,1}) -- 012 -> 101
end if
end if
-- second stage, pass 1, right to left, 011 -> 100
for i=length(res)-2 to 1 by -1 do
if res[i..i+2]={0,1,1} then res[i..i+2] = {1,0,0} end if
end for
-- second stage, pass 2, left to right, 011 -> 100
for i=1 to length(res)-2 do
if res[i..i+2]={0,1,1} then res[i..i+2] = {1,0,0} end if
end for
return to_int(res)
end function
function zadd(integer a, b)
sequence {sa,sb} = to_bits2(a,b)
return zcleanup(reverse(sq_add(sa,sb)))
end function
function zinc(integer a)
return zadd(a,0b1)
end function
function zsub(integer a, b)
sequence {sa,sb} = to_bits2(a,b)
sequence res = reverse(sq_sub(sa,sb))
-- (/not/ combined with the first pass of the add routine!)
for i=1 to length(res)-2 do
switch res[i..i+2] do
case {1, 0, 0}: res[i..i+2] = {0,1,1}
case {1,-1, 0}: res[i..i+2] = {0,0,1}
case {1,-1, 1}: res[i..i+2] = {0,0,2}
case {1, 0,-1}: res[i..i+2] = {0,1,0}
case {2, 0, 0}: res[i..i+2] = {1,1,1}
case {2,-1, 0}: res[i..i+2] = {1,0,1}
case {2,-1, 1}: res[i..i+2] = {1,0,2}
case {2, 0,-1}: res[i..i+2] = {1,1,0}
end switch
end for
-- copied from PicoLisp: {1,-1} -> {0,1} and {2,-1} -> {1,1}
for i=1 to length(res)-1 do
switch res[i..i+1] do
case {1,-1}: res[i..i+1] = {0,1}
case {2,-1}: res[i..i+1] = {1,1}
end switch
end for
if find(-1,res) then ?9/0 end if -- sanity check
return zcleanup(res)
end function
function zdec(integer a)
return zsub(a,0b1)
end function
function zmul(integer a, b)
integer res = 0
sequence mult = {a,zadd(a,a)} -- (as per task desc)
integer bits = 2
while bits<b do
mult = append(mult,zadd(mult[$],mult[$-1]))
bits *= 2
end while
integer bit = 1
while b do
if and_bits(b,1) then
res = zadd(res,mult[bit])
end if
b = floor(b/2)
bit += 1
end while
return res
end function
function zdiv(integer a, b)
integer res = 0
sequence mult = {b,zadd(b,b)}
integer bits = 2
while mult[$]<a do
mult = append(mult,zadd(mult[$],mult[$-1]))
bits *= 2
end while
for i=length(mult) to 1 by -1 do
integer mi = mult[i]
if mi<=a then
res = zadd(res,bits)
a = zsub(a,mi)
if a=0 then exit end if
end if
bits = floor(bits/2)
end for
return {res,a} -- (a is the remainder)
end function
for i=0 to 20 do
integer zi = zeckendorf(i)
atom d = decimal(zi)
printf(1,"%2d: %7b (%d)\n",{i,zi,d})
end for
procedure test(atom a, string op, atom b, object res, string expected)
string zres = iff(atom(res)?zstr(res):join(zstr(res)," rem ")),
dres = sprintf(iff(atom(res)?"%d":"%d rem %d"),decimal(res)),
aka = sprintf("aka %d %s %d = %s",{decimal(a),op,decimal(b),dres}),
ok = iff(zres=expected?"":" *** ERROR ***!!")
printf(1,"%s %s %s = %s, %s %s\n",{zstr(a),op,zstr(b),zres,aka,ok})
end procedure
test(0b0,"+",0b0,zadd(0b0,0b0),"0")
test(0b101,"+",0b101,zadd(0b101,0b101),"10000")
test(0b10100,"-",0b1000,zsub(0b10100,0b1000),"1001")
test(0b100100,"-",0b1000,zsub(0b100100,0b1000),"10100")
test(0b1001,"*",0b101,zmul(0b1001,0b101),"1000100")
test(0b1000101,"/",0b101,zdiv(0b1000101,0b101),"1001 rem 1")
test(0b10,"+",0b10,zadd(0b10,0b10),"101")
test(0b101,"+",0b10,zadd(0b101,0b10),"1001")
test(0b1001,"+",0b1001,zadd(0b1001,0b1001),"10101")
test(0b10101,"+",0b1000,zadd(0b10101,0b1000),"100101")
test(0b100101,"+",0b10101,zadd(0b100101,0b10101),"1010000")
test(0b1000,"-",0b101,zsub(0b1000,0b101),"1")
test(0b10101010,"-",0b1010101,zsub(0b10101010,0b1010101),"1000000")
test(0b1001,"*",0b101,zmul(0b1001,0b101),"1000100")
test(0b101010,"+",0b101,zadd(0b101010,0b101),"1000100")
test(0b10100,"+",0b1010,zadd(0b10100,0b1010),"101000")
test(0b101000,"-",0b1010,zsub(0b101000,0b1010),"10100")
test(0b100010,"*",0b100101,zmul(0b100010,0b100101),"100001000001")
test(0b100001000001,"/",0b100,zdiv(0b100001000001,0b100),"101010001 rem 0")
test(0b101000101,"*",0b101001,zmul(0b101000101,0b101001),"101010000010101")
test(0b101010000010101,"/",0b100,zdiv(0b101010000010101,0b100),"1001010001001 rem 10")
test(0b10100010010100,"+",0b1001000001,zadd(0b10100010010100,0b1001000001),"100000000010101")
test(0b10100010010100,"-",0b1001000001,zsub(0b10100010010100,0b1001000001),"10010001000010")
test(0b10000,"*",0b1001000001,zmul(0b10000,0b1001000001),"10100010010100")
test(0b1010001010000001001,"/",0b100000000100000,zdiv(0b1010001010000001001,0b100000000100000),"10001 rem 10100001010101")
test(0b10100,"+",0b1010,zadd(0b10100,0b1010),"101000")
test(0b10100,"-",0b1010,zsub(0b10100,0b1010),"101")
test(0b10100,"*",0b1010,zmul(0b10100,0b1010),"101000001")
test(0b10100,"/",0b1010,zdiv(0b10100,0b1010),"1 rem 101")
integer m = zmul(0b10100,0b1010)
test(m,"/",0b1010,zdiv(m,0b1010),"10100 rem 0")

View file

@ -0,0 +1,144 @@
import copy
class Zeckendorf:
def __init__(self, x='0'):
q = 1
i = len(x) - 1
self.dLen = int(i / 2)
self.dVal = 0
while i >= 0:
self.dVal = self.dVal + (ord(x[i]) - ord('0')) * q
q = q * 2
i = i -1
def a(self, n):
i = n
while True:
if self.dLen < i:
self.dLen = i
j = (self.dVal >> (i * 2)) & 3
if j == 0 or j == 1:
return
if j == 2:
if (self.dVal >> ((i + 1) * 2) & 1) != 1:
return
self.dVal = self.dVal + (1 << (i * 2 + 1))
return
if j == 3:
temp = 3 << (i * 2)
temp = temp ^ -1
self.dVal = self.dVal & temp
self.b((i + 1) * 2)
i = i + 1
def b(self, pos):
if pos == 0:
self.inc()
return
if (self.dVal >> pos) & 1 == 0:
self.dVal = self.dVal + (1 << pos)
self.a(int(pos / 2))
if pos > 1:
self.a(int(pos / 2) - 1)
else:
temp = 1 << pos
temp = temp ^ -1
self.dVal = self.dVal & temp
self.b(pos + 1)
self.b(pos - (2 if pos > 1 else 1))
def c(self, pos):
if (self.dVal >> pos) & 1 == 1:
temp = 1 << pos
temp = temp ^ -1
self.dVal = self.dVal & temp
return
self.c(pos + 1)
if pos > 0:
self.b(pos - 1)
else:
self.inc()
def inc(self):
self.dVal = self.dVal + 1
self.a(0)
def __add__(self, rhs):
copy = self
rhs_dVal = rhs.dVal
limit = (rhs.dLen + 1) * 2
for gn in range(0, limit):
if ((rhs_dVal >> gn) & 1) == 1:
copy.b(gn)
return copy
def __sub__(self, rhs):
copy = self
rhs_dVal = rhs.dVal
limit = (rhs.dLen + 1) * 2
for gn in range(0, limit):
if (rhs_dVal >> gn) & 1 == 1:
copy.c(gn)
while (((copy.dVal >> ((copy.dLen * 2) & 31)) & 3) == 0) or (copy.dLen == 0):
copy.dLen = copy.dLen - 1
return copy
def __mul__(self, rhs):
na = copy.deepcopy(rhs)
nb = copy.deepcopy(rhs)
nr = Zeckendorf()
dVal = self.dVal
for i in range(0, (self.dLen + 1) * 2):
if ((dVal >> i) & 1) > 0:
nr = nr + nb
nt = copy.deepcopy(nb)
nb = nb + na
na = copy.deepcopy(nt)
return nr
def __str__(self):
dig = ["00", "01", "10"]
dig1 = ["", "1", "10"]
if self.dVal == 0:
return '0'
idx = (self.dVal >> ((self.dLen * 2) & 31)) & 3
sb = dig1[idx]
i = self.dLen - 1
while i >= 0:
idx = (self.dVal >> (i * 2)) & 3
sb = sb + dig[idx]
i = i - 1
return sb
# main
print "Addition:"
g = Zeckendorf("10")
g = g + Zeckendorf("10")
print g
g = g + Zeckendorf("10")
print g
g = g + Zeckendorf("1001")
print g
g = g + Zeckendorf("1000")
print g
g = g + Zeckendorf("10101")
print g
print
print "Subtraction:"
g = Zeckendorf("1000")
g = g - Zeckendorf("101")
print g
g = Zeckendorf("10101010")
g = g - Zeckendorf("1010101")
print g
print
print "Multiplication:"
g = Zeckendorf("1001")
g = g * Zeckendorf("101")
print g
g = Zeckendorf("101010")
g = g + Zeckendorf("101")
print g