/* Interpreter of the Turing Machine. An initial CURRENT_STATE of the Turing Machine is coded by "start", final CURRENT_STATE - by "halt". The shift of the head to the right is designated through "R", to the left - through "L" . */ class Multiplication { public static int ltape = 50; /* Length of a tape */ public static int nunits1 = 4; /* It is 3 */ public static int nunits2 = 5; /* It is 4 */ public static int head; public static String state; /* Indexes in array of the instructions, */ public static final int CURRENT_STATE = 0; public static final int CURRENT_SYMBOL = 1; public static final int NEXT_SYMBOL = 3; public static final int NEXT_STATE = 2; public static final int MOVE = 4; public static String[] tape = new String[ltape]; /* http://www.ams.org/new-in-math/cover/turing_multiply_code.html # Turing machine to multiply two numbers: # Number n is represented by string of n+1 1's. # Initially, tape is assumed to be in form of _n1_n2_ (where _ is blank), # and head is assumed to be positioned at leftmost non-blank square. # Initial internal machine state is "start". # At halt, tape is _n1_n2_n3_, where n3=n1*n2, # and head is positioned at leftmost non-blank square. start, 1, move1right, W, R # mark first bit of 1st argument move1right, 1, move1right, 1, R # move right til past 1st argument move1right, _, mark2start, _, R # square between 1st and 2nd arguments found mark2start, 1, move2right, Y, R # mark first bit of 2nd argument move2right, 1, move2right, 1, R # move right til past 2nd argument move2right, _, initialize, _, R # square between 2nd argument and answer found initialize, _, backup, 1, L # put a 1 at start of answer backup, _, backup, _, L # move back to leftmost unused bit of 1st arg backup, 1, backup, 1, L # ditto backup, Z, backup, Z, L # ditto backup, Y, backup, Y, L # ditto backup, X, nextpass, X, R # in position to start next pass backup, W, nextpass, W, R # ditto nextpass, _, finishup, _, R # if square is blank, we're done. finish up nextpass, 1, findarg2, X, R # if square is not blank, go to work. mark bit findarg2, 1, findarg2, 1, R # move past 1st argument findarg2, _, findarg2, _, R # square between 1st and 2nd arguments findarg2, Y, testarg2, Y, R # start of 2nd arg. skip this bit, copy rest testarg2, _, cleanup2, _, L # if blank, we are done with this pass testarg2, 1, findans, Z, R # if not, increment ans. mark bit, move there findans, 1, findans, 1, R # still in 2nd argument findans, _, atans, _, R # square between 2nd argument and answer atans, 1, atans, 1, R # move through answer atans, _, backarg2, 1, L # at end of answer--write a 1 here, go back backarg2, 1, backarg2, 1, L # move left to first unused bit of 2nd arg backarg2, _, backarg2, _, L # ditto backarg2, Z, testarg2, Z, R # just past it. move right, and test it backarg2, Y, testarg2, Y, R # ditto cleanup2, 1, cleanup2, 1, L # move back through answer cleanup2, _, cleanup2, _, L # square between 2nd arg and answer cleanup2, Z, cleanup2, 1, L # restore bits of 2nd argument cleanup2, Y, backup, Y, L # done with that. backup to start next pass finishup, Y, finishup, 1, L # restore first bit of 2nd argument finishup, _, finishup, _, L # 2nd argument restored, move back to 1st finishup, X, finishup, 1, L # restore bits of 1st argument finishup, W, almostdone, 1, L # restore first bit of 1st arg. almost done almostdone, _, halt, _, R # done with work. position properly and halt */ public static final String[][] instruction = { { "start", "1", "move1right", "W", "R" }, { "move1right", "1", "move1right", "1", "R" }, { "move1right", "_", "mark2start", "_", "R" }, { "mark2start", "1", "move2right", "Y", "R" }, { "move2right", "1", "move2right", "1", "R" }, { "move2right", "_", "initialize", "_", "R" }, { "initialize", "_", "backup", "1", "L" }, { "backup", "_", "backup", "_", "L" }, { "backup", "1", "backup", "1", "L" }, { "backup", "Z", "backup", "Z", "L" }, { "backup", "Y", "backup", "Y", "L" }, { "backup", "X", "nextpass", "X", "R" }, { "backup", "W", "nextpass", "W", "R" }, { "nextpass", "_", "finishup", "_", "R" }, { "nextpass", "1", "findarg2", "X", "R" }, { "findarg2", "1", "findarg2", "1", "R" }, { "findarg2", "_", "findarg2", "_", "R" }, { "findarg2", "Y", "testarg2", "Y", "R" }, { "testarg2", "_", "cleanup2", "_", "L" }, { "testarg2", "1", "findans", "Z", "R" }, { "findans", "1", "findans", "1", "R" }, { "findans", "_", "atans", "_", "R" }, { "atans", "1", "atans", "1", "R" }, { "atans", "_", "backarg2", "1", "L" }, { "backarg2", "1", "backarg2", "1", "L" }, { "backarg2", "_", "backarg2", "_", "L" }, { "backarg2", "Z", "testarg2", "Z", "R" }, { "backarg2", "Y", "testarg2", "Y", "R" }, { "cleanup2", "1", "cleanup2", "1", "L" }, { "cleanup2", "_", "cleanup2", "_", "L" }, { "cleanup2", "Z", "cleanup2", "1", "L" }, { "cleanup2", "Y", "backup", "Y", "L" }, { "finishup", "Y", "finishup", "1", "L" }, { "finishup", "_", "finishup", "_", "L" }, { "finishup", "X", "finishup", "1", "L" }, { "finishup", "W", "almostdone", "1", "L" }, { "almostdone", "_", "halt", "_", "R" } }; public static void main (String args[]) { head = ltape/2; /* the head in the middle of a tape */ for (int i = 0; i < ltape; i++) { /* filling of blank */ tape[i] = "_"; } for (int i = head; i < head+nunits1; i++) { tape[i] = "1"; } for (int i = head+nunits1+1; i < head+nunits1+1+nunits2; i++) { tape[i] = "1"; } long start = System.currentTimeMillis(); test(); long end = System.currentTimeMillis(); System.out.println("Total time = "+ (end-start)*0.001); System.out.println("Final Tape : " ); for (int i = 0; i < ltape; i++) System.out.print(tape[i]) ; } public static void test() { state = "start"; while (state != "halt") { for (int i=0; i<instruction.length; i++) { if (state == instruction[i][CURRENT_STATE] && tape[head] == instruction[i][CURRENT_SYMBOL]) { state=instruction[i][NEXT_STATE]; tape[head]=instruction[i][NEXT_SYMBOL]; if(instruction[i][MOVE]=="R") head++; if(instruction[i][MOVE]=="L" ) head--; } } } } }