// Consider binary trees with integer values at the leaves, 
// and problems of 
//  (i) summing these values,
//  (ii) counting all nodes+leaves.
//
// Solution using Visitor pattern.
//
abstract class Tree {
    abstract void accept(TreeVisitor v);
};


class Node extends Tree {
    Tree left, right;
    Node (Tree left, Tree right) {
	this.left = left; this.right = right;
    }
    void accept(TreeVisitor v) {
	v.visitNode(this);
    }
}


class Leaf extends Tree {
    int value;
    Leaf (int value) {
	this.value = value;
    }
    void accept(TreeVisitor v) {
	v.visitLeaf(this);
    }
}


interface TreeVisitor {  // Note: methods are implicitly public
    void visitNode(Node x);
    void visitLeaf(Leaf x);
}

class TreeSumVisitor implements TreeVisitor {
    int sum = 0;
    public void visitNode(Node x) {
	x.left.accept(this);
	x.right.accept(this);
    }
    public void visitLeaf(Leaf x) {
	sum += x.value;
    }
}

class TreeCountVisitor implements TreeVisitor {
    int count = 0;
    public void visitNode(Node x) {
	x.left.accept(this);
	x.right.accept(this);
	count++;
    }
    public void visitLeaf(Leaf x) {
	count++;
    }
}

class TreeOps {
    static int sum(Tree t) {
	TreeSumVisitor v = new TreeSumVisitor();
	t.accept(v);
	return v.sum;
    }
    static int count(Tree t) {
	TreeCountVisitor v = new TreeCountVisitor();
	t.accept(v);
	return v.count;
    }
}

class TestTree {
    public static void main(String argv[]) {
	Tree t = new Node (new Leaf(1), new Node(new Leaf(2), new Leaf(3)));
	int sum = TreeOps.sum(t);
	int count = TreeOps.count(t);
	System.out.println("Sum = " + sum);
	System.out.println("Count = " + count);
    }
}

