Task: Zeckendorf arithmetic





Java: import java.util.List;

public class Zeckendorf implements Comparable<Zeckendorf> {
    private static List<String> dig = List.of("00", "01", "10");
    private static List<String> dig1 = List.of("", "1", "10");

    private String x;
    private int dVal = 0;
    private int dLen = 0;

    public Zeckendorf() {
        this("0");
    }

    public Zeckendorf(String x) {
        this.x = x;

        int q = 1;
        int i = x.length() - 1;
        dLen = i / 2;
        while (i >= 0) {
            dVal += (x.charAt(i) - '0') * q;
            q *= 2;
            i--;
        }
    }

    private void a(int n) {
        int i = n;
        while (true) {
            if (dLen < i) dLen = i;
            int j = (dVal >> (i * 2)) & 3;
            switch (j) {
                case 0:
                case 1:
                    return;
                case 2:
                    if (((dVal >> ((i + 1) * 2)) & 1) != 1) return;
                    dVal += 1 << (i * 2 + 1);
                    return;
                case 3:
                    int temp = 3 << (i * 2);
                    temp ^= -1;
                    dVal = dVal & temp;
                    b((i + 1) * 2);
                    break;
            }
            i++;
        }
    }

    private void b(int pos) {
        if (pos == 0) {
            Zeckendorf thiz = this;
            thiz.inc();
            return;
        }
        if (((dVal >> pos) & 1) == 0) {
            dVal += 1 << pos;
            a(pos / 2);
            if (pos > 1) a(pos / 2 - 1);
        } else {
            int temp = 1 << pos;
            temp ^= -1;
            dVal = dVal & temp;
            b(pos + 1);
            b(pos - (pos > 1 ? 2 : 1));
        }
    }

    private void c(int pos) {
        if (((dVal >> pos) & 1) == 1) {
            int temp = 1 << pos;
            temp ^= -1;
            dVal = dVal & temp;
            return;
        }
        c(pos + 1);
        if (pos > 0) {
            b(pos - 1);
        } else {
            Zeckendorf thiz = this;
            thiz.inc();
        }
    }

    public Zeckendorf inc() {
        dVal++;
        a(0);
        return this;
    }

    public void plusAssign(Zeckendorf other) {
        for (int gn = 0; gn < (other.dLen + 1) * 2; gn++) {
            if (((other.dVal >> gn) & 1) == 1) {
                b(gn);
            }
        }
    }

    public void minusAssign(Zeckendorf other) {
        for (int gn = 0; gn < (other.dLen + 1) * 2; gn++) {
            if (((other.dVal >> gn) & 1) == 1) {
                c(gn);
            }
        }
        while ((((dVal >> dLen * 2) & 3) == 0) || (dLen == 0)) {
            dLen--;
        }
    }

    public void timesAssign(Zeckendorf other) {
        Zeckendorf na = other.copy();
        Zeckendorf nb = other.copy();
        Zeckendorf nt;
        Zeckendorf nr = new Zeckendorf();
        for (int i = 0; i < (dLen + 1) * 2; i++) {
            if (((dVal >> i) & 1) > 0) {
                nr.plusAssign(nb);
            }
            nt = nb.copy();
            nb.plusAssign(na);
            na = nt.copy();
        }
        dVal = nr.dVal;
        dLen = nr.dLen;
    }

    private Zeckendorf copy() {
        Zeckendorf z = new Zeckendorf();
        z.dVal = dVal;
        z.dLen = dLen;
        return z;
    }

    @Override
    public int compareTo(Zeckendorf other) {
        return ((Integer) dVal).compareTo(other.dVal);
    }

    @Override
    public String toString() {
        if (dVal == 0) {
            return "0";
        }

        int idx = (dVal >> (dLen * 2)) & 3;
        StringBuilder stringBuilder = new StringBuilder(dig1.get(idx));
        for (int i = dLen - 1; i >= 0; i--) {
            idx = (dVal >> (i * 2)) & 3;
            stringBuilder.append(dig.get(idx));
        }
        return stringBuilder.toString();
    }

    public static void main(String[] args) {
        System.out.println("Addition:");
        Zeckendorf g = new Zeckendorf("10");
        g.plusAssign(new Zeckendorf("10"));
        System.out.println(g);
        g.plusAssign(new Zeckendorf("10"));
        System.out.println(g);
        g.plusAssign(new Zeckendorf("1001"));
        System.out.println(g);
        g.plusAssign(new Zeckendorf("1000"));
        System.out.println(g);
        g.plusAssign(new Zeckendorf("10101"));
        System.out.println(g);

        System.out.println("\nSubtraction:");
        g = new Zeckendorf("1000");
        g.minusAssign(new Zeckendorf("101"));
        System.out.println(g);
        g = new Zeckendorf("10101010");
        g.minusAssign(new Zeckendorf("1010101"));
        System.out.println(g);

        System.out.println("\nMultiplication:");
        g = new Zeckendorf("1001");
        g.timesAssign(new Zeckendorf("101"));
        System.out.println(g);
        g = new Zeckendorf("101010");
        g.plusAssign(new Zeckendorf("101"));
        System.out.println(g);
    }
}




VB: Imports System.Text

Module Module1

    Class Zeckendorf
        Implements IComparable(Of Zeckendorf)

        Private Shared ReadOnly dig As String() = {"00", "01", "10"}
        Private Shared ReadOnly dig1 As String() = {"", "1", "10"}

        Private dVal As Integer = 0
        Private dLen As Integer = 0

        Public Sub New(Optional x As String = "0")
            Dim q = 1
            Dim i = x.Length - 1
            dLen = i \ 2

            Dim z = Asc("0")
            While i >= 0
                Dim a = Asc(x(i))
                dVal += (a - z) * q
                q *= 2
                i -= 1
            End While
        End Sub

        Private Sub A(n As Integer)
            Dim i = n
            While True
                If dLen < i Then
                    dLen = i
                End If
                Dim j = (dVal >> (i * 2)) And 3
                If j = 0 OrElse j = 1 Then
                    Return
                ElseIf j = 2 Then
                    If ((dVal >> ((i + 1) * 2)) And 1) <> 1 Then
                        Return
                    End If
                    dVal += 1 << (i * 2 + 1)
                    Return
                ElseIf j = 3 Then
                    Dim temp = 3 << (i * 2)
                    temp = temp Xor -1
                    dVal = dVal And temp
                    B((i + 1) * 2)
                End If
                i += 1
            End While
        End Sub

        Private Sub B(pos As Integer)
            If pos = 0 Then
                Inc()
                Return
            End If
            If ((dVal >> pos) And 1) = 0 Then
                dVal += 1 << pos
                A(pos \ 2)
                If pos > 1 Then
                    A(pos \ 2 - 1)
                End If
            Else
                Dim temp = 1 << pos
                temp = temp Xor -1
                dVal = dVal And temp
                B(pos + 1)
                B(pos - If(pos > 1, 2, 1))
            End If
        End Sub

        Private Sub C(pos As Integer)
            If ((dVal >> pos) And 1) = 1 Then
                Dim temp = 1 << pos
                temp = temp Xor -1
                dVal = dVal And temp
                Return
            End If
            C(pos + 1)
            If pos > 0 Then
                B(pos - 1)
            Else
                Inc()
            End If
        End Sub

        Public Function Inc() As Zeckendorf
            dVal += 1
            A(0)
            Return Me
        End Function

        Public Function Copy() As Zeckendorf
            Dim z As New Zeckendorf With {
                .dVal = dVal,
                .dLen = dLen
            }
            Return z
        End Function

        Public Sub PlusAssign(other As Zeckendorf)
            Dim gn = 0
            While gn < (other.dLen + 1) * 2
                If ((other.dVal >> gn) And 1) = 1 Then
                    B(gn)
                End If
                gn += 1
            End While
        End Sub

        Public Sub MinusAssign(other As Zeckendorf)
            Dim gn = 0
            While gn < (other.dLen + 1) * 2
                If ((other.dVal >> gn) And 1) = 1 Then
                    C(gn)
                End If
                gn += 1
            End While
            While (((dVal >> dLen * 2) And 3) = 0) OrElse dLen = 0
                dLen -= 1
            End While
        End Sub

        Public Sub TimesAssign(other As Zeckendorf)
            Dim na = other.Copy
            Dim nb = other.Copy
            Dim nt As Zeckendorf
            Dim nr As New Zeckendorf
            Dim i = 0
            While i < (dLen + 1) * 2
                If ((dVal >> i) And 1) > 0 Then
                    nr.PlusAssign(nb)
                End If
                nt = nb.Copy
                nb.PlusAssign(na)
                na = nt.Copy
                i += 1
            End While
            dVal = nr.dVal
            dLen = nr.dLen
        End Sub

        Public Function CompareTo(other As Zeckendorf) As Integer Implements IComparable(Of Zeckendorf).CompareTo
            Return dVal.CompareTo(other.dVal)
        End Function

        Public Overrides Function ToString() As String
            If dVal = 0 Then
                Return "0"
            End If

            Dim idx = (dVal >> (dLen * 2)) And 3
            Dim sb As New StringBuilder(dig1(idx))
            Dim i = dLen - 1
            While i >= 0
                idx = (dVal >> (i * 2)) And 3
                sb.Append(dig(idx))
                i -= 1
            End While
            Return sb.ToString
        End Function
    End Class

    Sub Main()
        Console.WriteLine("Addition:")
        Dim g As New Zeckendorf("10")
        g.PlusAssign(New Zeckendorf("10"))
        Console.WriteLine(g)
        g.PlusAssign(New Zeckendorf("10"))
        Console.WriteLine(g)
        g.PlusAssign(New Zeckendorf("1001"))
        Console.WriteLine(g)
        g.PlusAssign(New Zeckendorf("1000"))
        Console.WriteLine(g)
        g.PlusAssign(New Zeckendorf("10101"))
        Console.WriteLine(g)
        Console.WriteLine()

        Console.WriteLine("Subtraction:")
        g = New Zeckendorf("1000")
        g.MinusAssign(New Zeckendorf("101"))
        Console.WriteLine(g)
        g = New Zeckendorf("10101010")
        g.MinusAssign(New Zeckendorf("1010101"))
        Console.WriteLine(g)
        Console.WriteLine()

        Console.WriteLine("Multiplication:")
        g = New Zeckendorf("1001")
        g.TimesAssign(New Zeckendorf("101"))
        Console.WriteLine(g)
        g = New Zeckendorf("101010")
        g.PlusAssign(New Zeckendorf("101"))
        Console.WriteLine(g)
    End Sub

End Module