Task: Balanced ternary


C++: #include <iostream>
#include <string>
#include <climits>
using namespace std;

class BalancedTernary {
protected:
	
	string value;

	
	int charToInt(char c) const {
		if (c == '0')
			return 0;
		return 44 - c;
	}

	
	string negate(string s) const {
		for (int i = 0; i < s.length(); ++i) {
			if (s[i] == '+')
				s[i] = '-';
			else if (s[i] == '-')
				s[i] = '+';
		}
		return s;
	}

public:
	
	BalancedTernary() {
		value = "0";
	}

	
	BalancedTernary(string s) {
		value = string(s.rbegin(), s.rend());
	}

	
	BalancedTernary(long long n) {
		if (n == 0) {
			value = "0";
			return;
		}

		bool neg = n < 0;
		if (neg) 
			n = -n;

		value = "";
		while (n != 0) {
			int r = n % 3;
			if (r == 0)
				value += "0";
			else if (r == 1)
				value += "+";
			else {
				value += "-";
				++n;
			}

			n /= 3;
		}

		if (neg)
			value = negate(value);
	}

	
	BalancedTernary(const BalancedTernary &n) {
		value = n.value;
	}

	
	BalancedTernary operator+(BalancedTernary n) const {
		n += *this;
		return n;
	}

	BalancedTernary& operator+=(const BalancedTernary &n) {
		static char *add = "0+-0+-0";
		static char *carry = "--000++";

		int lastNonZero = 0;
		char c = '0';
		for (int i = 0; i < value.length() || i < n.value.length(); ++i) {
			char a = i < value.length() ? value[i] : '0';
			char b = i < n.value.length() ? n.value[i] : '0';

			int sum = charToInt(a) + charToInt(b) + charToInt(c) + 3;
			c = carry[sum];

			if (i < value.length())
				value[i] = add[sum];
			else
				value += add[sum];

			if (add[sum] != '0')
				lastNonZero = i;
		}

		if (c != '0')
			value += c;
		else
			value = value.substr(0, lastNonZero + 1); 

		return *this;
	}

	
	BalancedTernary operator-() const {
		BalancedTernary result;
		result.value = negate(value);
		return result;
	}

	
	BalancedTernary operator-(const BalancedTernary &n) const {
		return operator+(-n);
	}

	BalancedTernary& operator-=(const BalancedTernary &n) {
		return operator+=(-n);
	}

	
	BalancedTernary operator*(BalancedTernary n) const {
		n *= *this;
		return n;
	}

	BalancedTernary& operator*=(const BalancedTernary &n) {
		BalancedTernary pos = *this;
		BalancedTernary neg = -pos; 
		value = "0";

		for (int i = 0; i < n.value.length(); ++i) {
			if (n.value[i] == '+')
				operator+=(pos);
			else if (n.value[i] == '-')
				operator+=(neg);
			pos.value = '0' + pos.value;
			neg.value = '0' + neg.value;
		}

		return *this;
	}

	
	friend ostream& operator<<(ostream &out, const BalancedTernary &n) {
		out << n.toString();
		return out;
	}

	
	string toString() const {
		return string(value.rbegin(), value.rend());
	}

	
	long long toInt() const {
		long long result = 0;
		for (long long i = 0, pow = 1; i < value.length(); ++i, pow *= 3)
			result += pow * charToInt(value[i]);
		return result;
	}

	
	bool tryInt(long long &out) const {
		long long result = 0;
		bool ok = true;

		for (long long i = 0, pow = 1; i < value.length() && ok; ++i, pow *= 3) {
			if (value[i] == '+') {
				ok &= LLONG_MAX - pow >= result; 
				result += pow;
			} else if (value[i] == '-') {
				ok &= LLONG_MIN + pow <= result; 
				result -= pow;
			}
		}

		if (ok)
			out = result;
		return ok;
	}
};

int main() {
	BalancedTernary a("+-0++0+");
	BalancedTernary b(-436);
	BalancedTernary c("+-++-");

	cout << "a = " << a << " = " << a.toInt() << endl;
	cout << "b = " << b << " = " << b.toInt() << endl;
	cout << "c = " << c << " = " << c.toInt() << endl;

	BalancedTernary d = a * (b - c);

	cout << "a * (b - c) = " << d << " = " << d.toInt() << endl;

	BalancedTernary e("+++++++++++++++++++++++++++++++++++++++++");

	long long n;
	if (e.tryInt(n))
		cout << "e = " << e << " = " << n << endl;
	else
		cout << "e = " << e << " is too big to fit in a long long" << endl;

	return 0;
}






Python: class BalancedTernary:
    

    str2dig = {'+': 1, '-': -1, '0': 0} 
    dig2str = {1: '+', -1: '-', 0: '0'} 
    table = ((0, -1), (1, -1), (-1, 0), (0, 0), (1, 0), (-1, 1), (0, 1)) 

    def __init__(self, inp):
        if isinstance(inp, str):
            self.digits = [BalancedTernary.str2dig[c] for c in reversed(inp)]
        elif isinstance(inp, int):
            self.digits = self._int2ternary(inp)
        elif isinstance(inp, BalancedTernary):
            self.digits = list(inp.digits)
        elif isinstance(inp, list):
            if all(d in (0, 1, -1) for d in inp):
                self.digits = list(inp)
            else:
                raise ValueError("BalancedTernary: Wrong input digits.")
        else:
            raise TypeError("BalancedTernary: Wrong constructor input.")

    @staticmethod
    def _int2ternary(n):
        if n == 0: return []
        if (n % 3) == 0: return [0] + BalancedTernary._int2ternary(n // 3)
        if (n % 3) == 1: return [1] + BalancedTernary._int2ternary(n // 3)
        if (n % 3) == 2: return [-1] + BalancedTernary._int2ternary((n + 1) // 3)

    def to_int(self):
        return reduce(lambda y,x: x + 3 * y, reversed(self.digits), 0)

    def __repr__(self):
        if not self.digits: return "0"
        return "".join(BalancedTernary.dig2str[d] for d in reversed(self.digits))

    @staticmethod
    def _neg(digs):
        return [-d for d in digs]

    def __neg__(self):
        return BalancedTernary(BalancedTernary._neg(self.digits))

    @staticmethod
    def _add(a, b, c=0):
        if not (a and b):
            if c == 0:
                return a or b
            else:
                return BalancedTernary._add([c], a or b)
        else:
            (d, c) = BalancedTernary.table[3 + (a[0] if a else 0) + (b[0] if b else 0) + c]
            res = BalancedTernary._add(a[1:], b[1:], c)
            
            if res or d != 0:
                return [d] + res
            else:
                return res

    def __add__(self, b):
        return BalancedTernary(BalancedTernary._add(self.digits, b.digits))

    def __sub__(self, b):
        return self + (-b)

    @staticmethod
    def _mul(a, b):
        if not (a and b):
            return []
        else:
            if   a[0] == -1: x = BalancedTernary._neg(b)
            elif a[0] ==  0: x = []
            elif a[0] ==  1: x = b
            else: assert False
            y = [0] + BalancedTernary._mul(a[1:], b)
            return BalancedTernary._add(x, y)

    def __mul__(self, b):
        return BalancedTernary(BalancedTernary._mul(self.digits, b.digits))


def main():
    a = BalancedTernary("+-0++0+")
    print "a:", a.to_int(), a

    b = BalancedTernary(-436)
    print "b:", b.to_int(), b

    c = BalancedTernary("+-++-")
    print "c:", c.to_int(), c

    r = a * (b - c)
    print "a * (b - c):", r.to_int(), r

main()