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




Java: 
public class BalancedTernary 
{
	public static void main(String[] args)
	{
 		BTernary a=new BTernary("+-0++0+");
		BTernary b=new BTernary(-436);
		BTernary c=new BTernary("+-++-");
		
		System.out.println("a="+a.intValue());
		System.out.println("b="+b.intValue());
		System.out.println("c="+c.intValue());
		System.out.println();
		
		
		BTernary result=a.mul(b.sub(c));
		
		System.out.println("result= "+result+" "+result.intValue());
	}
	
	
	public static class BTernary
	{
		String value;
		public BTernary(String s)
		{
			int i=0;
			while(s.charAt(i)=='0')
				i++;
			this.value=s.substring(i);
		}
		public BTernary(int v)
		{
			this.value="";
			this.value=convertToBT(v);
		}
		
		private String convertToBT(int v)
		{
			if(v<0)
				return flip(convertToBT(-v));
			if(v==0)
				return "";
			int rem=mod3(v);
			if(rem==0)
				return convertToBT(v/3)+"0";
			if(rem==1)
				return convertToBT(v/3)+"+";
			if(rem==2)
				return convertToBT((v+1)/3)+"-";
			return "You can't see me";
		}
		private String flip(String s)
		{
			String flip="";
			for(int i=0;i<s.length();i++)
			{
				if(s.charAt(i)=='+')
					flip+='-';
				else if(s.charAt(i)=='-')
					flip+='+';
				else
					flip+='0';
			}
			return flip;
		}
		private int mod3(int v)
		{
			if(v>0)
				return v%3;
			v=v%3;
			return (v+3)%3;
		}
		
		public int intValue()
		{
			int sum=0;
			String s=this.value;
			for(int i=0;i<s.length();i++)
			{
				char c=s.charAt(s.length()-i-1);
				int dig=0;
				if(c=='+')
					dig=1;
				else if(c=='-')
					dig=-1;
				sum+=dig*Math.pow(3, i);
			}
			return sum;
		}
		
		
		public BTernary add(BTernary that)
		{
			String a=this.value;
			String b=that.value;
			
			String longer=a.length()>b.length()?a:b;
			String shorter=a.length()>b.length()?b:a;
			
			while(shorter.length()<longer.length())
				shorter=0+shorter;
			
			a=longer;
			b=shorter;
			
			char carry='0';
			String sum="";
			for(int i=0;i<a.length();i++)
			{
				int place=a.length()-i-1;
				String digisum=addDigits(a.charAt(place),b.charAt(place),carry);
				if(digisum.length()!=1)
					carry=digisum.charAt(0);
				else
					carry='0';
				sum=digisum.charAt(digisum.length()-1)+sum;
			}
			sum=carry+sum;
			
			return new BTernary(sum);
		}
		private String addDigits(char a,char b,char carry)
		{
			String sum1=addDigits(a,b);
			String sum2=addDigits(sum1.charAt(sum1.length()-1),carry);
			
			if(sum1.length()==1)
				return sum2;
			if(sum2.length()==1)
				return sum1.charAt(0)+sum2;
			return sum1.charAt(0)+"";
		}
		private String addDigits(char a,char b)
		{
			String sum="";
			if(a=='0')
				sum=b+"";
			else if (b=='0')
				sum=a+"";
			else if(a=='+')
			{
				if(b=='+')
					sum="+-";
				else
					sum="0";
			}
			else
			{
				if(b=='+')
					sum="0";
				else
					sum="-+";
			}
			return sum;
		}
		
		public BTernary neg()
		{
			return new BTernary(flip(this.value));
		}
		
		public BTernary sub(BTernary that)
		{
			return this.add(that.neg());
		}
		
		public BTernary mul(BTernary that)
		{
			BTernary one=new BTernary(1);
			BTernary zero=new BTernary(0);
			BTernary mul=new BTernary(0);
			
			int flipflag=0;
			if(that.compareTo(zero)==-1)
			{
				that=that.neg();
				flipflag=1;
			}
			for(BTernary i=new BTernary(1);i.compareTo(that)<1;i=i.add(one))
				mul=mul.add(this);
			
			if(flipflag==1)
				mul=mul.neg();
			return mul;
		}
		
		public boolean equals(BTernary that)
		{
			return this.value.equals(that.value);
		}
		public int compareTo(BTernary that)
		{
			if(this.intValue()>that.intValue())
				return 1;
			else if(this.equals(that))
				return 0;
			 return -1;
		}
		
		public String toString()
		{
			return value;
		}
	}
}