diff --git a/turing/Action.java b/turing/Action.java new file mode 100644 index 0000000..09b7a14 --- /dev/null +++ b/turing/Action.java @@ -0,0 +1,4 @@ +@FunctionalInterface +public interface Action { + void execute(); +} diff --git a/turing/Number.java b/turing/Number.java new file mode 100644 index 0000000..cb75783 --- /dev/null +++ b/turing/Number.java @@ -0,0 +1,177 @@ +public class Number { + private class NumberWrapper { + Number n; + } + + static class Zero extends Number { + public Zero() { + super(null); + } + + @Override + public void executeIfZero(Action action) { + action.execute(); + } + + @Override + public void executeIfNotZero(Action action) { + } + + @Override + public int value() { + return 0; + } + + @Override + public void executeIfEquals(Number n, Action a) { + n.executeIfZero(a); + } + } + + static class NegativeNumber extends Number { + private Number positive; + + public NegativeNumber(Number p) { + super(null); + positive = p; + } + + @Override + public Number succ() { + NumberWrapper w = new NumberWrapper(); + + positive.executeIfZero(() -> { + w.n = zero().succ(); + }); + + positive.executeIfNotZero(() -> { + w.n = new NegativeNumber(positive.pre); + }); + + return w.n; + } + + @Override + public Number pre() { + return new NegativeNumber(positive.succ()); + } + + @Override + public int value() { + return -positive.value(); + } + + @Override + public void executeIfNegative(Action a) { + a.execute(); + } + + @Override + public void executeIfNotNegative(Action a) { + } + + @Override + public void executeIfZero(Action a) { + positive.executeIfZero(a); + } + + @Override + public void executeIfNotZero(Action a) { + positive.executeIfNotZero(a); + } + + @Override + public void executeIfEquals(Number n, Action a) { + n.executeIfNegative(() -> { + positive.executeIfEquals(((NegativeNumber) n).positive, a); + }); + } + + @Override + public void forEach(Action a) { + positive.forEach(a); + } + } + + private Number pre; + + private Number(Number pre) { + this.pre = pre; + } + + public static Number zero() { + return new Zero(); + } + + public Number succ() { + return new Number(this); + } + + public void forEach(Action a) { + executeIfNotZero(() -> { + a.execute(); + pre.forEach(a); + }); + } + + public Number add(Number n) { + NumberWrapper w = new NumberWrapper(); + w.n = this; + + n.executeIfNegative(() -> { + n.forEach(() -> { + w.n = w.n.pre(); + }); + }); + n.executeIfNotNegative(() -> { + n.forEach(() -> { + w.n = w.n.succ(); + }); + }); + + return w.n; + } + + public Number pre() { + NumberWrapper w = new NumberWrapper(); + executeIfZero(() -> { + w.n = new NegativeNumber(succ()); + }); + + executeIfNotZero(() -> { + w.n = pre; + }); + + return w.n; + } + + public void executeIfZero(Action action) { + } + + public void executeIfNotZero(Action action) { + action.execute(); + } + + public int value() { + return this.pre.value() + 1; + } + + public void executeIfEquals(Number n, Action a) { + n.executeIfNotNegative(() -> { + n.executeIfNotZero(() -> { + pre.executeIfEquals(n.pre, a); + }); + }); + } + + public void executeIfNegative(Action a) { + } + + public void executeIfNotNegative(Action a) { + a.execute(); + } + + public String toString() { + return String.valueOf(value()); + } +} diff --git a/turing/StateMachine.java b/turing/StateMachine.java new file mode 100644 index 0000000..cbdb459 --- /dev/null +++ b/turing/StateMachine.java @@ -0,0 +1,91 @@ +public class StateMachine { + public static final Number END_STATE = Number.zero(); + + public static final Number READ_LEFT = END_STATE.succ(); + public static final Number EXPECT_0_RIGHT = READ_LEFT.succ(); + public static final Number EXPECT_0_RIGHT_CHECK = EXPECT_0_RIGHT.succ(); + public static final Number EXPECT_1_RIGHT = EXPECT_0_RIGHT_CHECK.succ(); + public static final Number EXPECT_1_RIGHT_CHECK = EXPECT_1_RIGHT.succ(); + + public static final Number READ_RIGHT = EXPECT_1_RIGHT_CHECK.succ(); + public static final Number EXPECT_0_LEFT = READ_RIGHT.succ(); + public static final Number EXPECT_0_LEFT_CHECK = EXPECT_0_LEFT.succ(); + public static final Number EXPECT_1_LEFT = EXPECT_0_LEFT_CHECK.succ(); + public static final Number EXPECT_1_LEFT_CHECK = EXPECT_1_LEFT.succ(); + + public static final int INITIAL_STATE = READ_LEFT.value(); + + public static final Number zero = Number.zero(); + public static final Number one = Number.zero().succ(); + public static final Number minusOne = Number.zero().pre(); + + public class Transition { + Number nextState; + char write; + Number move; + + public Transition(Number nextState, char write, Number move) { + this.nextState = nextState; + this.write = write; + this.move = move; + } + } + + private Transition table[][]; + int currentState = INITIAL_STATE; + + private Action onHalt; + + public StateMachine(Action onHalt) { + + this.onHalt = onHalt; + + table = new Transition[11][256]; + + table[READ_LEFT.value()]['1'] = new Transition(EXPECT_1_RIGHT, ' ', one); + table[READ_LEFT.value()]['0'] = new Transition(EXPECT_0_RIGHT, ' ', one); + table[READ_LEFT.value()][' '] = new Transition(END_STATE, ' ', zero); + + table[EXPECT_1_RIGHT.value()]['1'] = new Transition(EXPECT_1_RIGHT, '1', one); + table[EXPECT_1_RIGHT.value()]['0'] = new Transition(EXPECT_1_RIGHT, '0', one); + table[EXPECT_1_RIGHT.value()][' '] = new Transition(EXPECT_1_RIGHT_CHECK, ' ', minusOne); + table[EXPECT_1_RIGHT_CHECK.value()]['1'] = new Transition(READ_RIGHT, ' ', minusOne); + table[EXPECT_1_RIGHT_CHECK.value()]['0'] = new Transition(EXPECT_1_RIGHT_CHECK, ' ', zero); + table[EXPECT_1_RIGHT_CHECK.value()][' '] = new Transition(EXPECT_1_RIGHT_CHECK, ' ', zero); // loop endless + + table[EXPECT_0_RIGHT.value()]['1'] = new Transition(EXPECT_0_RIGHT, '1', one); + table[EXPECT_0_RIGHT.value()]['0'] = new Transition(EXPECT_0_RIGHT, '0', one); + table[EXPECT_0_RIGHT.value()][' '] = new Transition(EXPECT_0_RIGHT_CHECK, ' ', minusOne); + table[EXPECT_0_RIGHT_CHECK.value()]['0'] = new Transition(READ_RIGHT, ' ', minusOne); + table[EXPECT_0_RIGHT_CHECK.value()]['1'] = new Transition(EXPECT_0_RIGHT_CHECK, ' ', zero); + table[EXPECT_0_RIGHT_CHECK.value()][' '] = new Transition(EXPECT_0_RIGHT_CHECK, ' ', zero); // loop endless + + table[READ_RIGHT.value()]['1'] = new Transition(EXPECT_1_LEFT, ' ', minusOne); + table[READ_RIGHT.value()]['0'] = new Transition(EXPECT_0_LEFT, ' ', minusOne); + table[READ_RIGHT.value()][' '] = new Transition(END_STATE, ' ', zero); + + table[EXPECT_1_LEFT.value()]['1'] = new Transition(EXPECT_1_LEFT, '1', minusOne); + table[EXPECT_1_LEFT.value()]['0'] = new Transition(EXPECT_1_LEFT, '0', minusOne); + table[EXPECT_1_LEFT.value()][' '] = new Transition(EXPECT_1_LEFT_CHECK, ' ', one); + table[EXPECT_1_LEFT_CHECK.value()]['1'] = new Transition(READ_LEFT, ' ', one); + table[EXPECT_1_LEFT_CHECK.value()]['0'] = new Transition(EXPECT_1_LEFT_CHECK, ' ', zero); + table[EXPECT_1_LEFT_CHECK.value()][' '] = new Transition(EXPECT_1_LEFT_CHECK, ' ', zero); // loop endless + + table[EXPECT_0_LEFT.value()]['1'] = new Transition(EXPECT_0_LEFT, '1', minusOne); + table[EXPECT_0_LEFT.value()]['0'] = new Transition(EXPECT_0_LEFT, '0', minusOne); + table[EXPECT_0_LEFT.value()][' '] = new Transition(EXPECT_0_LEFT_CHECK, ' ', one); + table[EXPECT_0_LEFT_CHECK.value()]['0'] = new Transition(READ_LEFT, ' ', one); + table[EXPECT_0_LEFT_CHECK.value()]['1'] = new Transition(EXPECT_0_LEFT_CHECK, ' ', zero); + table[EXPECT_0_LEFT_CHECK.value()][' '] = new Transition(EXPECT_0_LEFT_CHECK, ' ', zero); // loop endless + } + + public Transition stateChange(char input) { + Transition t = table[currentState][input]; + + t.nextState.executeIfZero(onHalt); + + currentState = t.nextState.value(); + + return t; + } +} diff --git a/turing/Tape.java b/turing/Tape.java new file mode 100644 index 0000000..15a3c5a --- /dev/null +++ b/turing/Tape.java @@ -0,0 +1,38 @@ +public class Tape { + + private class CharWrapper { + char c; + } + + @FunctionalInterface + private interface Cell { + char value(Number i); + } + + private Cell cells; + + public Tape() { + cells = (i) -> ' '; + } + + public char get(Number i) { + return cells.value(i); + } + + public void set(Number i, char c) { + + final Cell _cells = cells; + + cells = (j) -> { + CharWrapper w = new CharWrapper(); + + w.c = _cells.value(j); + + j.executeIfEquals(i, () -> { + w.c = c; + }); + + return w.c; + }; + } +} diff --git a/turing/TuringMachine.java b/turing/TuringMachine.java new file mode 100644 index 0000000..ae3e240 --- /dev/null +++ b/turing/TuringMachine.java @@ -0,0 +1,55 @@ +public class TuringMachine { + + private Tape tape; + private StateMachine sm; + private Number position; + + public TuringMachine() { + tape = new Tape(); + sm = new StateMachine(() -> { + System.out.println("halted"); + System.exit(0); + }); + + position = Number.zero(); + + Number n = Number.zero(); + tape.set(n, '0'); + n = n.succ(); + tape.set(n, '1'); + n = n.succ(); + tape.set(n, '1'); + n = n.succ(); + tape.set(n, '0'); + n = n.succ(); + tape.set(n, '0'); + n = n.succ(); + tape.set(n, '1'); + n = n.succ(); + tape.set(n, '1'); + n = n.succ(); + tape.set(n, '0'); + } + + public void step() { + Number oldPosition = position; + char in = tape.get(position); + int state = sm.currentState; + StateMachine.Transition t = sm.stateChange(in); + tape.set(position, t.write); + position = position.add(t.move); + + //System.out.println(state + ", " + oldPosition + ", " + in + " -> " + t.nextState + ", " + t.write + ", " + position); + + step(); + } + + public void run() { + step(); + } + + public static void main(String[] args) { + TuringMachine tm = new TuringMachine(); + tm.run(); + } +}