diff --git a/99bottles/Bottles.java b/99bottles/Bottles.java new file mode 100644 index 0000000..f9d570a --- /dev/null +++ b/99bottles/Bottles.java @@ -0,0 +1,197 @@ +public class Bottles { + @FunctionalInterface + static private interface Action { + void execute(); + } + @FunctionalInterface + static private interface Consumer { + void take(T t); + } + + static private class NumberWrapper { + public Number number; + + public NumberWrapper(Number n) { + number = n; + } + } + + static private class CompareResult { + private Number r1; + private Number r2; + + public CompareResult(Number r1, Number r2) { + this.r1 = r1; + this.r2 = r2; + } + + public void executeIfEqual(Action action) { + r1.executeIfZero(() -> { + r2.executeIfZero(action); + }); + } + + public void executeIfGreaterOrEqual(Action action) { + r2.executeIfZero(action); + } + + public void executeIfLessOrEqual(Action action) { + r1.executeIfZero(action); + } + + public void executeIfGreater(Action action) { + r2.executeIfZero(() -> { + r1.executeIfNotZero(action); + }); + } + public void executeIfLess(Action action) { + r1.executeIfZero(() -> { + r2.executeIfNotZero(action); + }); + } + } + + static private class Number { + private Number predecessor; + + public Number(Number pre) { + predecessor = pre; + } + + public Number clone() { + return new Number(predecessor); + } + + public static Number succ(Number pre) { + return new Number(pre); + } + + public static Number zero() { + return new Zero(); + } + + public static Number one() { + return succ(zero()); + } + + public static Number two() { + return succ(one()); + } + + public Number pre() { + return predecessor; + } + + public static Number add(Number n1, Number n2) { + NumberWrapper wrapper = new NumberWrapper(zero()); + + n1.forEach((n) -> { + wrapper.number = succ(wrapper.number); + }); + + n2.forEach((n) -> { + wrapper.number = succ(wrapper.number); + }); + + return wrapper.number; + } + + public static Number multiply(Number n1, Number n2) { + NumberWrapper wrapper = new NumberWrapper(zero()); + + n1.forEach((n) -> { + wrapper.number = add(wrapper.number, n2); + }); + + return wrapper.number; + } + + public int value() { + return predecessor.value() + 1; + } + + public void executeIfZero(Action action) { + } + + public void executeIfNotZero(Action action) { + action.execute(); + } + + public void forEach(Consumer consumer) { + executeIfNotZero(() -> { + consumer.take(this); + predecessor.forEach(consumer); + }); + } + + public static Number subtract(Number n1, Number n2) { + NumberWrapper wrapper = new NumberWrapper(n1.clone()); + + n2.forEach((n) -> { + wrapper.number = wrapper.number.pre(); + }); + + return wrapper.number; + } + + public CompareResult compare(Number compare) { + return new CompareResult(subtract(this, compare), subtract(compare, this)); + } + + public String toString() { + return String.valueOf(value()); + } + } + + static private class Zero extends Number { + public Zero() { + super(null); + } + + @Override + public Number clone() { + return new Zero(); + } + + @Override + public int value() { + return 0; + } + + @Override + public void executeIfZero(Action action) { + action.execute(); + } + + @Override + public void executeIfNotZero(Action action) { + } + + @Override + public Number pre() { + return this; + } + } + + + + public static void main(String[] args) { + Number one = Number.one(); + Number five = Number.add(Number.add(Number.two(), Number.two()), one); + Number ten = Number.multiply(five, Number.two()); + Number hundred = Number.multiply(ten, ten); + Number nintynine = hundred.pre(); + + nintynine.forEach((n) -> { + CompareResult cr = n.compare(one); + cr.executeIfGreater(() -> { + System.out.println(n + " bottles of beer on the wall."); + }); + cr.executeIfEqual(() -> { + System.out.println("One bottle of beer on the wall."); + }); + }); + + System.out.println("No bottles of beer on the wall."); + } +}