class RunnyStack { class Run { public Base object; public int length; public Run next; public Run(Base object, Run next) { this.object = object; this.length = 1; this.next = next; } public Run(Base object) { this(object, null); } public boolean is(Base other) { if (other == null || this.object == null) { return this.object == other; } else { return this.object.equals(other); } } } private int runs, depth; private Run top; public RunnyStack() { this.runs = 0; this.depth = 0; this.top = null; } public boolean isEmpty() { return this.top == null; } public int depth() { return this.depth; } public int runs() { return this.runs; } public void push(Base object) { Run run = new Run(object, top); if (this.top == null) { this.runs = 1; this.depth = 1; this.top = run; } else { if (this.top.is(object)) { this.depth += 1; this.top.length += 1; } else { this.runs += 1; this.depth += 1; Run top = this.top; run.next = top; this.top = run; } } } public void pop() { if (this.isEmpty()) { throw new IllegalStateException("The stack is empty."); } this.depth -= 1; this.top.length -= 1; if (this.top.length == 0) { this.runs -= 1; this.top = this.top.next; } } public Base peek() { if (this.isEmpty()) { throw new IllegalStateException("The stack is empty."); } return this.top.object; } } class RunnyDriver { public static void main(String[] args) { RunnyStack s = new RunnyStack(); s.push("A"); System.out.println(s.peek() + " " + s.depth() + " " + s.runs()); // A 1 1 s.push("B"); System.out.println(s.peek() + " " + s.depth() + " " + s.runs()); // B 2 2 s.push("B"); System.out.println(s.peek() + " " + s.depth() + " " + s.runs()); // B 3 2 s.pop(); System.out.println(s.peek() + " " + s.depth() + " " + s.runs()); // B 2 2 s.pop(); System.out.println(s.peek() + " " + s.depth() + " " + s.runs()); // A 1 1 } }