RosettaCodeData/Task/Zeckendorf-arithmetic/Elena/zeckendorf-arithmetic.elena
2026-02-01 16:33:20 -08:00

251 lines
4.8 KiB
Text

import extensions;
const string[] dig = new []{"00","01","10"};
const string[] dig1 = new []{"","1","10"};
sealed struct ZeckendorfNumber
{
int dVal : rprop();
int dLen : rprop();
constructor()
{
dVal := 0;
dLen := 0
}
clone()
= ZeckendorfNumber.newInternal(dVal,dLen);
cast n(string s)
{
int i := s.Length - 1;
int q := 1;
dLen := i / 2;
dVal := 0;
while (i >= 0)
{
dVal += ((s[i].toInt() - 48) * q);
q *= 2;
i -= 1
}
}
private a(int n)
{
int i := n;
while (true)
{
if (dLen < i)
{
dLen := i;
};
int v := (dVal shr:(i * 2)) & 3;
v =>
0 : { ^ self }
1 : { ^ self }
2 : {
if:not ((dVal shr:((i + 1) * 2)).allMask(1))
{
^ self
};
dVal += (1 shl:(i*2 + 1));
^ self
}
3 : {
int tmp := 3 shl: (i * 2);
tmp := tmp ^ -1;
dVal := dVal & tmp;
self.b((i+1)*2)
};
i += 1
}
}
inc()
{
dVal += 1;
self.a(0)
}
private b(int pos)
{
if (pos == 0) { ^ self.inc() };
if:not((dVal shr:pos).allMask(1))
{
dVal += (1 shl:pos);
self.a(pos / 2);
if (pos > 1) { self.a((pos / 2) - 1) }
}
else
{
int temp := 1 shl:pos;
temp := temp ^ -1;
dVal := dVal & temp;
self.b(pos + 1);
int arg := pos - ((pos > 1) ? 2 : 1);
self.b(/*pos - ((pos > 1) ? 2 : 1)*/arg)
}
}
private c(int pos)
{
if ((dVal shr:pos).allMask(1))
{
int tmp := 1 shl:pos;
tmp := tmp.bxor(-1);
dVal := dVal & tmp;
^ self
};
self.c(pos + 1);
if (pos > 0)
{
self.b(pos - 1)
}
else
{
self.inc()
}
}
internal constructor sum(ZeckendorfNumber n, ZeckendorfNumber m)
{
int mVal := m.dVal;
int mLen := m.dLen;
dVal := n.dVal;
dLen := n.dLen;
for(int GN := 0; GN < (mLen + 1) * 2; GN += 1)
{
if ((mVal shr:GN).allMask(1))
{
self.b(GN)
}
}
}
internal constructor difference(ZeckendorfNumber n, ZeckendorfNumber m)
{
int mVal := m.dVal;
int mLen := m.dLen;
dVal := n.dVal;
dLen := n.dLen;
for(int GN := 0; GN < (mLen + 1) * 2; GN += 1)
{
if ((mVal shr:GN).allMask(1))
{
self.c(GN)
}
};
while (((dVal shr:(dLen*2)) & 3) == 0 || dLen == 0)
{
dLen -= 1
}
}
internal constructor product(ZeckendorfNumber n, ZeckendorfNumber m)
{
dVal := n.dVal;
dLen := n.dLen;
ZeckendorfNumber Na := m;
ZeckendorfNumber Nb := m;
ZeckendorfNumber Nr := 0n;
ZeckendorfNumber Nt := 0n;
for(int i := 0; i < (dLen + 1) * 2; i += 1)
{
if (((dVal $shr i) & 1) > 0)
{
Nr += Nb
};
Nt := Nb;
Nb += Na;
Na := Nt
};
dVal := Nr.dVal;
dLen := Nr.dLen;
}
internal constructor newInternal(int v, int l)
{
dVal := v;
dLen := l
}
string toPrintable()
{
if (dVal == 0)
{ ^ "0" };
string s := dig1[(dVal $shr (dLen * 2)) & 3];
for (int i := dLen - 1; i >= 0; i--)
{
s := s + dig[(dVal $shr (i * 2)) & 3];
};
^ s
}
add(ZeckendorfNumber n)
= ZeckendorfNumber.sum(self, n);
subtract(ZeckendorfNumber n)
= ZeckendorfNumber.difference(self, n);
multiply(ZeckendorfNumber n)
= ZeckendorfNumber.product(self, n);
}
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);
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)
}