Task: Zeckendorf arithmetic
C: #include <stdbool.h>
#include <stdio.h>
#include <string.h>

int inv(int a) {
    return a ^ -1;
}

struct Zeckendorf {
    int dVal, dLen;
};

void a(struct Zeckendorf *self, int n) {
    void b(struct Zeckendorf *, int); 

    int i = n;
    while (true) {
        if (self->dLen < i) self->dLen = i;
        int j = (self->dVal >> (i * 2)) & 3;
        switch (j) {
        case 0:
        case 1:
            return;
        case 2:
            if (((self->dVal >> ((i + 1) * 2)) & 1) != 1) return;
            self->dVal += 1 << (i * 2 + 1);
            return;
        case 3:
            self->dVal = self->dVal & inv(3 << (i * 2));
            b(self, (i + 1) * 2);
            break;
        default:
            break;
        }
        i++;
    }
}

void b(struct Zeckendorf *self, int pos) {
    void increment(struct Zeckendorf *); 

    if (pos == 0) {
        increment(self);
        return;
    }
    if (((self->dVal >> pos) & 1) == 0) {
        self->dVal += 1 << pos;
        a(self, pos / 2);
        if (pos > 1) a(self, pos / 2 - 1);
    } else {
        self->dVal = self->dVal & inv(1 << pos);
        b(self, pos + 1);
        b(self, pos - (pos > 1 ? 2 : 1));
    }
}

void c(struct Zeckendorf *self, int pos) {
    if (((self->dVal >> pos) & 1) == 1) {
        self->dVal = self->dVal & inv(1 << pos);
        return;
    }
    c(self, pos + 1);
    if (pos > 0) {
        b(self, pos - 1);
    } else {
        increment(self);
    }
}

struct Zeckendorf makeZeckendorf(char *x) {
    struct Zeckendorf z = { 0, 0 };
    int i = strlen(x) - 1;
    int q = 1;

    z.dLen = i / 2;
    while (i >= 0) {
        z.dVal += (x[i] - '0') * q;
        q *= 2;
        i--;
    }

    return z;
}

void increment(struct Zeckendorf *self) {
    self->dVal++;
    a(self, 0);
}

void addAssign(struct Zeckendorf *self, struct Zeckendorf rhs) {
    int gn;
    for (gn = 0; gn < (rhs.dLen + 1) * 2; gn++) {
        if (((rhs.dVal >> gn) & 1) == 1) {
            b(self, gn);
        }
    }
}

void subAssign(struct Zeckendorf *self, struct Zeckendorf rhs) {
    int gn;
    for (gn = 0; gn < (rhs.dLen + 1) * 2; gn++) {
        if (((rhs.dVal >> gn) & 1) == 1) {
            c(self, gn);
        }
    }
    while ((((self->dVal >> self->dLen * 2) & 3) == 0) || (self->dLen == 0)) {
        self->dLen--;
    }
}

void mulAssign(struct Zeckendorf *self, struct Zeckendorf rhs) {
    struct Zeckendorf na = rhs;
    struct Zeckendorf nb = rhs;
    struct Zeckendorf nr = makeZeckendorf("0");
    struct Zeckendorf nt;
    int i;

    for (i = 0; i < (self->dLen + 1) * 2; i++) {
        if (((self->dVal >> i) & 1) > 0) addAssign(&nr, nb);
        nt = nb;
        addAssign(&nb, na);
        na = nt;
    }

    *self = nr;
}

void printZeckendorf(struct Zeckendorf z) {
    static const char *const dig[3] = { "00", "01", "10" };
    static const char *const dig1[3] = { "", "1", "10" };

    if (z.dVal == 0) {
        printf("0");
        return;
    } else {
        int idx = (z.dVal >> (z.dLen * 2)) & 3;
        int i;

        printf(dig1[idx]);
        for (i = z.dLen - 1; i >= 0; i--) {
            idx = (z.dVal >> (i * 2)) & 3;
            printf(dig[idx]);
        }
    }
}

int main() {
    struct Zeckendorf g;

    printf("Addition:\n");
    g = makeZeckendorf("10");
    addAssign(&g, makeZeckendorf("10"));
    printZeckendorf(g);
    printf("\n");
    addAssign(&g, makeZeckendorf("10"));
    printZeckendorf(g);
    printf("\n");
    addAssign(&g, makeZeckendorf("1001"));
    printZeckendorf(g);
    printf("\n");
    addAssign(&g, makeZeckendorf("1000"));
    printZeckendorf(g);
    printf("\n");
    addAssign(&g, makeZeckendorf("10101"));
    printZeckendorf(g);
    printf("\n\n");

    printf("Subtraction:\n");
    g = makeZeckendorf("1000");
    subAssign(&g, makeZeckendorf("101"));
    printZeckendorf(g);
    printf("\n");
    g = makeZeckendorf("10101010");
    subAssign(&g, makeZeckendorf("1010101"));
    printZeckendorf(g);
    printf("\n\n");

    printf("Multiplication:\n");
    g = makeZeckendorf("1001");
    mulAssign(&g, makeZeckendorf("101"));
    printZeckendorf(g);
    printf("\n");
    g = makeZeckendorf("101010");
    addAssign(&g, makeZeckendorf("101"));
    printZeckendorf(g);
    printf("\n");

    return 0;
}

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);
    }
}