Task: Balanced ternary

C: #include <stdio.h>
#include <string.h>

void reverse(char *p) {
    size_t len = strlen(p);
    char *r = p + len - 1;
    while (p < r) {
        *p ^= *r;
        *r ^= *p;
        *p++ ^= *r--;
    }
}

void to_bt(int n, char *b) {
    static char d[] = { '0', '+', '-' };
    static int v[] = { 0, 1, -1 };

    char *ptr = b;
    *ptr = 0;

    while (n) {
        int r = n % 3;
        if (r < 0) {
            r += 3;
        }

        *ptr = d[r];
        *(++ptr) = 0;

        n -= v[r];
        n /= 3;
    }

    reverse(b);
}

int from_bt(const char *a) {
    int n = 0;

    while (*a != '\0') {
        n *= 3;
        if (*a == '+') {
            n++;
        } else if (*a == '-') {
            n--;
        }
        a++;
    }

    return n;
}

char last_char(char *ptr) {
    char c;

    if (ptr == NULL || *ptr == '\0') {
        return '\0';
    }

    while (*ptr != '\0') {
        ptr++;
    }
    ptr--;

    c = *ptr;
    *ptr = 0;
    return c;
}

void add(const char *b1, const char *b2, char *out) {
    if (*b1 != '\0' && *b2 != '\0') {
        char c1[16];
        char c2[16];
        char ob1[16];
        char ob2[16];
        char d[3] = { 0, 0, 0 };
        char L1, L2;

        strcpy(c1, b1);
        strcpy(c2, b2);
        L1 = last_char(c1);
        L2 = last_char(c2);
        if (L2 < L1) {
            L2 ^= L1;
            L1 ^= L2;
            L2 ^= L1;
        }

        if (L1 == '-') {
            if (L2 == '0') {
                d[0] = '-';
            }
            if (L2 == '-') {
                d[0] = '+';
                d[1] = '-';
            }
        }
        if (L1 == '+') {
            if (L2 == '0') {
                d[0] = '+';
            }
            if (L2 == '-') {
                d[0] = '0';
            }
            if (L2 == '+') {
                d[0] = '-';
                d[1] = '+';
            }
        }
        if (L1 == '0') {
            if (L2 == '0') {
                d[0] = '0';
            }
        }

        add(c1, &d[1], ob1);
        add(ob1, c2, ob2);
        strcpy(out, ob2);

        d[1] = 0;
        strcat(out, d);
    } else if (*b1 != '\0') {
        strcpy(out, b1);
    } else if (*b2 != '\0') {
        strcpy(out, b2);
    } else {
        *out = '\0';
    }
}

void unary_minus(const char *b, char *out) {
    while (*b != '\0') {
        if (*b == '-') {
            *out++ = '+';
            b++;
        } else if (*b == '+') {
            *out++ = '-';
            b++;
        } else {
            *out++ = *b++;
        }
    }
    *out = '\0';
}

void subtract(const char *b1, const char *b2, char *out) {
    char buf[16];
    unary_minus(b2, buf);
    add(b1, buf, out);
}

void mult(const char *b1, const char *b2, char *out) {
    char r[16] = "0";
    char t[16];
    char c1[16];
    char c2[16];
    char *ptr = c2;

    strcpy(c1, b1);
    strcpy(c2, b2);

    reverse(c2);

    while (*ptr != '\0') {
        if (*ptr == '+') {
            add(r, c1, t);
            strcpy(r, t);
        }
        if (*ptr == '-') {
            subtract(r, c1, t);
            strcpy(r, t);
        }
        strcat(c1, "0");

        ptr++;
    }

    ptr = r;
    while (*ptr == '0') {
        ptr++;
    }
    strcpy(out, ptr);
}

int main() {
    const char *a = "+-0++0+";
    char b[16];
    const char *c = "+-++-";
    char t[16];
    char d[16];

    to_bt(-436, b);
    subtract(b, c, t);
    mult(a, t, d);

    printf("      a: %14s %10d\n", a, from_bt(a));
    printf("      b: %14s %10d\n", b, from_bt(b));
    printf("      c: %14s %10d\n", c, from_bt(c));
    printf("a*(b-c): %14s %10d\n", d, from_bt(d));

    return 0;
}








VB: Imports System.Text

Module Module1
    Sub Main()
        Dim a As New BalancedTernary("+-0++0+")
        Console.WriteLine("a: {0} = {1}", a, a.ToLong)
        Dim b As New BalancedTernary(-436)
        Console.WriteLine("b: {0} = {1}", b, b.ToLong)
        Dim c As New BalancedTernary("+-++-")
        Console.WriteLine("c: {0} = {1}", c, c.ToLong)
        Dim d = a * (b - c)
        Console.WriteLine("a * (b - c): {0} = {1}", d, d.ToLong)
    End Sub

    Class BalancedTernary
        Private Enum BalancedTernaryDigit
            MINUS = -1
            ZERO = 0
            PLUS = 1
        End Enum

        Private ReadOnly value() As BalancedTernaryDigit

        
        Public Sub New()
            ReDim value(-1)
        End Sub

        
        Public Sub New(str As String)
            ReDim value(str.Length - 1)
            For i = 1 To str.Length
                If str(i - 1) = "-" Then
                    value(i - 1) = BalancedTernaryDigit.MINUS
                ElseIf str(i - 1) = "0" Then
                    value(i - 1) = BalancedTernaryDigit.ZERO
                ElseIf str(i - 1) = "+" Then
                    value(i - 1) = BalancedTernaryDigit.PLUS
                Else
                    Throw New ArgumentException("Unknown Digit: " + str(i - 1))
                End If
            Next
            Array.Reverse(value)
        End Sub

        
        Public Sub New(l As Long)
            Dim value As New List(Of BalancedTernaryDigit)
            Dim sign = Math.Sign(l)
            l = Math.Abs(l)

            While l <> 0
                Dim remainder = CType(l Mod 3, Byte)
                If remainder = 0 OrElse remainder = 1 Then
                    value.Add(remainder)
                    l /= 3
                ElseIf remainder = 2 Then
                    value.Add(BalancedTernaryDigit.MINUS)
                    l = (l + 1) / 3
                End If
            End While

            Me.value = value.ToArray
            If sign < 0 Then
                Invert()
            End If
        End Sub

        
        Public Sub New(origin As BalancedTernary)
            ReDim value(origin.value.Length - 1)
            Array.Copy(origin.value, value, origin.value.Length)
        End Sub

        
        Private Sub New(value() As BalancedTernaryDigit)
            Dim endi = value.Length - 1
            While endi > 0 AndAlso value(endi) = BalancedTernaryDigit.ZERO
                endi -= 1
            End While
            ReDim Me.value(endi)
            Array.Copy(value, Me.value, endi + 1)
        End Sub

        
        Private Sub Invert()
            For i = 1 To value.Length
                value(i - 1) = CType(-CType(value(i - 1), Integer), BalancedTernaryDigit)
            Next
        End Sub

        
        Public Overrides Function ToString() As String
            Dim result As New StringBuilder
            Dim i = value.Length - 1
            While i >= 0
                If value(i) = BalancedTernaryDigit.MINUS Then
                    result.Append("-")
                ElseIf value(i) = BalancedTernaryDigit.ZERO Then
                    result.Append("0")
                ElseIf value(i) = BalancedTernaryDigit.PLUS Then
                    result.Append("+")
                End If

                i -= 1
            End While
            Return result.ToString
        End Function

        
        Public Function ToLong() As Long
            Dim result = 0L
            For i = 1 To value.Length
                result += value(i - 1) * Math.Pow(3.0, i - 1)
            Next
            Return result
        End Function

        
        Public Shared Operator -(origin As BalancedTernary) As BalancedTernary
            Dim result As New BalancedTernary(origin)
            result.Invert()
            Return result
        End Operator

        
        Private Shared carry = BalancedTernaryDigit.ZERO
        Private Shared Function Add(a As BalancedTernaryDigit, b As BalancedTernaryDigit) As BalancedTernaryDigit
            If a <> b Then
                carry = BalancedTernaryDigit.ZERO
                Return a + b
            Else
                carry = a
                Return -CType(b, Integer)
            End If
        End Function

        
        Public Shared Operator +(a As BalancedTernary, b As BalancedTernary) As BalancedTernary
            Dim maxLength = Math.Max(a.value.Length, b.value.Length)
            Dim resultValue(maxLength) As BalancedTernaryDigit
            For i = 1 To maxLength
                If i - 1 < a.value.Length Then
                    resultValue(i - 1) = Add(resultValue(i - 1), a.value(i - 1))
                    resultValue(i) = carry
                Else
                    carry = BalancedTernaryDigit.ZERO
                End If

                If i - 1 < b.value.Length Then
                    resultValue(i - 1) = Add(resultValue(i - 1), b.value(i - 1))
                    resultValue(i) = Add(resultValue(i), carry)
                End If
            Next
            Return New BalancedTernary(resultValue)
        End Operator

        
        Public Shared Operator -(a As BalancedTernary, b As BalancedTernary) As BalancedTernary
            Return a + (-b)
        End Operator

        
        Public Shared Operator *(a As BalancedTernary, b As BalancedTernary) As BalancedTernary
            Dim longValue = a.value
            Dim shortValue = b.value
            Dim result As New BalancedTernary

            If a.value.Length < b.value.Length Then
                longValue = b.value
                shortValue = a.value
            End If

            For i = 1 To shortValue.Length
                If shortValue(i - 1) <> BalancedTernaryDigit.ZERO Then
                    Dim temp(i + longValue.Length - 2) As BalancedTernaryDigit
                    For j = 1 To longValue.Length
                        temp(i + j - 2) = CType(shortValue(i - 1) * longValue(j - 1), BalancedTernaryDigit)
                    Next
                    result += New BalancedTernary(temp)
                End If
            Next

            Return result
        End Operator
    End Class

End Module