class Ratio {
	private int numerator;
	private int denominator;
	public Ratio(int num, int denom) {
	// pre: denom != 0
		numerator = num;
		denominator = denom;
		reduce();
	}

	public int getNumerator() {
		return numerator;
	}

	public int getDenominator() {
		return denominator;
	}

	public double getValue() {
		return (double)numerator/(double)denominator;
	}

	public Ratio add(Ratio other) {
		int newnum = numerator*other.denominator + denominator*other.numerator;
		int newdenom = denominator*other.denominator;
		return new Ratio(newnum, newdenom);
	}

	private void reduce() {
		int divisor = rgcd(numerator, denominator);
		//System.out.println("reduce: gcd of {0} and {1} is {2}", numerator, denominator, divisor);
		if (denominator < 0) divisor = -divisor;
		numerator = numerator / divisor;
		denominator = denominator / divisor;
	}

	// recursive version
	private static int rgcd(int a, int b) {
		System.out.format("rgcd(%s,%s) called%n", a, b);
		if (a<0) return gcd(-a, b);
		if (a==0) {
		    if (b==0) return 1;
		    return b;
		}
		if (b<a) return rgcd(b,a);
		return rgcd(b%a, a);
	}

	// non-recursive version
	private static int gcd(int a, int b) {
	    if (a<0) a=-a;
	    if (b<0) b=-b;
	    while (a>0 && b>0) {
       		if (a>=b) a = a % b;
       		else b = b % a;
    	    }
    	    if (a==0) return b; else return a;
	}	

	public  int getHashCode() {
		System.out.format("getHashCode called for %s%n", toString());
		return 37;
	}

	/* */
	public String toString() {
		//System.out.println("calling toString on (" + numerator + "/" + denominator + ")");
		return "" + '(' + numerator + "/" + denominator + ')';
	}
	/* */
}