2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -5,10 +5,12 @@ Indeed one way to definitively prove that a language
is [[wp:Turing_completeness|turing-complete]]
is to implement a universal Turing machine in it.
'''The task'''
For this task you would simulate such a machine capable
;Task:
Simulate such a machine capable
of taking the definition of any other Turing machine and executing it.
Of course, you will not have an infinite tape,
but you should emulate this as much as is possible.
@ -18,6 +20,7 @@ To test your universal Turing machine (and prove your programming language
is Turing complete!), you should execute the following two Turing machines
based on the following definitions.
'''Simple incrementer'''
* '''States:''' q0, qf
* '''Initial state:''' q0
@ -28,8 +31,10 @@ based on the following definitions.
** (q0, 1, 1, right, q0)
** (q0, B, 1, stay, qf)
<br>
The input for this machine should be a tape of <code>1 1 1</code>
'''Three-state busy beaver'''
* '''States:''' a, b, c, halt
* '''Initial state:''' a
@ -44,8 +49,10 @@ The input for this machine should be a tape of <code>1 1 1</code>
** (c, 0, 1, left, b)
** (c, 1, 1, stay, halt)
<br>
The input for this machine should be an empty tape.
'''Bonus:'''
'''5-state, 2-symbol probable Busy Beaver machine from Wikipedia'''
@ -66,6 +73,8 @@ The input for this machine should be an empty tape.
** (E, 0, 1, stay, H)
** (E, 1, 0, left, A)
<br>
The input for this machine should be an empty tape.
This machine runs for more than 47 millions steps.
<br><br>

View file

@ -0,0 +1,231 @@
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
enum {
LEFT,
RIGHT,
STAY
};
typedef struct {
int state1;
int symbol1;
int symbol2;
int dir;
int state2;
} transition_t;
typedef struct tape_t tape_t;
struct tape_t {
int symbol;
tape_t *left;
tape_t *right;
};
typedef struct {
int states_len;
char **states;
int final_states_len;
int *final_states;
int symbols_len;
char *symbols;
int blank;
int state;
int tape_len;
tape_t *tape;
int transitions_len;
transition_t ***transitions;
} turing_t;
int state_index (turing_t *t, char *state) {
int i;
for (i = 0; i < t->states_len; i++) {
if (!strcmp(t->states[i], state)) {
return i;
}
}
return 0;
}
int symbol_index (turing_t *t, char symbol) {
int i;
for (i = 0; i < t->symbols_len; i++) {
if (t->symbols[i] == symbol) {
return i;
}
}
return 0;
}
void move (turing_t *t, int dir) {
tape_t *orig = t->tape;
if (dir == RIGHT) {
if (orig && orig->right) {
t->tape = orig->right;
}
else {
t->tape = calloc(1, sizeof (tape_t));
t->tape->symbol = t->blank;
if (orig) {
t->tape->left = orig;
orig->right = t->tape;
}
}
}
else if (dir == LEFT) {
if (orig && orig->left) {
t->tape = orig->left;
}
else {
t->tape = calloc(1, sizeof (tape_t));
t->tape->symbol = t->blank;
if (orig) {
t->tape->right = orig;
orig->left = t->tape;
}
}
}
}
turing_t *create (int states_len, ...) {
va_list args;
va_start(args, states_len);
turing_t *t = malloc(sizeof (turing_t));
t->states_len = states_len;
t->states = malloc(states_len * sizeof (char *));
int i;
for (i = 0; i < states_len; i++) {
t->states[i] = va_arg(args, char *);
}
t->final_states_len = va_arg(args, int);
t->final_states = malloc(t->final_states_len * sizeof (int));
for (i = 0; i < t->final_states_len; i++) {
t->final_states[i] = state_index(t, va_arg(args, char *));
}
t->symbols_len = va_arg(args, int);
t->symbols = malloc(t->symbols_len);
for (i = 0; i < t->symbols_len; i++) {
t->symbols[i] = va_arg(args, int);
}
t->blank = symbol_index(t, va_arg(args, int));
t->state = state_index(t, va_arg(args, char *));
t->tape_len = va_arg(args, int);
t->tape = NULL;
for (i = 0; i < t->tape_len; i++) {
move(t, RIGHT);
t->tape->symbol = symbol_index(t, va_arg(args, int));
}
if (!t->tape_len) {
move(t, RIGHT);
}
while (t->tape->left) {
t->tape = t->tape->left;
}
t->transitions_len = va_arg(args, int);
t->transitions = malloc(t->states_len * sizeof (transition_t **));
for (i = 0; i < t->states_len; i++) {
t->transitions[i] = malloc(t->symbols_len * sizeof (transition_t *));
}
for (i = 0; i < t->transitions_len; i++) {
transition_t *tran = malloc(sizeof (transition_t));
tran->state1 = state_index(t, va_arg(args, char *));
tran->symbol1 = symbol_index(t, va_arg(args, int));
tran->symbol2 = symbol_index(t, va_arg(args, int));
tran->dir = va_arg(args, int);
tran->state2 = state_index(t, va_arg(args, char *));
t->transitions[tran->state1][tran->symbol1] = tran;
}
va_end(args);
return t;
}
void print_state (turing_t *t) {
printf("%-10s ", t->states[t->state]);
tape_t *tape = t->tape;
while (tape->left) {
tape = tape->left;
}
while (tape) {
if (tape == t->tape) {
printf("[%c]", t->symbols[tape->symbol]);
}
else {
printf(" %c ", t->symbols[tape->symbol]);
}
tape = tape->right;
}
printf("\n");
}
void run (turing_t *t) {
int i;
while (1) {
print_state(t);
for (i = 0; i < t->final_states_len; i++) {
if (t->final_states[i] == t->state) {
return;
}
}
transition_t *tran = t->transitions[t->state][t->tape->symbol];
t->tape->symbol = tran->symbol2;
move(t, tran->dir);
t->state = tran->state2;
}
}
int main () {
printf("Simple incrementer\n");
turing_t *t = create(
/* states */ 2, "q0", "qf",
/* final_states */ 1, "qf",
/* symbols */ 2, 'B', '1',
/* blank */ 'B',
/* initial_state */ "q0",
/* initial_tape */ 3, '1', '1', '1',
/* transitions */ 2,
"q0", '1', '1', RIGHT, "q0",
"q0", 'B', '1', STAY, "qf"
);
run(t);
printf("\nThree-state busy beaver\n");
t = create(
/* states */ 4, "a", "b", "c", "halt",
/* final_states */ 1, "halt",
/* symbols */ 2, '0', '1',
/* blank */ '0',
/* initial_state */ "a",
/* initial_tape */ 0,
/* transitions */ 6,
"a", '0', '1', RIGHT, "b",
"a", '1', '1', LEFT, "c",
"b", '0', '1', LEFT, "a",
"b", '1', '1', RIGHT, "b",
"c", '0', '1', LEFT, "b",
"c", '1', '1', STAY, "halt"
);
run(t);
return 0;
printf("\nFive-state two-symbol probable busy beaver\n");
t = create(
/* states */ 6, "A", "B", "C", "D", "E", "H",
/* final_states */ 1, "H",
/* symbols */ 2, '0', '1',
/* blank */ '0',
/* initial_state */ "A",
/* initial_tape */ 0,
/* transitions */ 10,
"A", '0', '1', RIGHT, "B",
"A", '1', '1', LEFT, "C",
"B", '0', '1', RIGHT, "C",
"B", '1', '1', RIGHT, "B",
"C", '0', '1', RIGHT, "D",
"C", '1', '0', LEFT, "E",
"D", '0', '1', LEFT, "A",
"D", '1', '1', LEFT, "D",
"E", '0', '1', STAY, "H",
"E", '1', '0', LEFT, "A"
);
run(t);
}

View file

@ -0,0 +1,5 @@
200 I = STATE*NSYMBOL - ICHAR(TAPE(HEAD)) !Index the transition.
TAPE(HEAD) = MARK(I) !Do it. Possibly not changing the symbol.
HEAD = HEAD + MOVE(I) !Possibly not moving the head.
STATE = ICHAR(NEXT(I)) !Hopefully, something has changed!
IF (STATE.GT.0) GO TO 200 !Otherwise, we might loop forever...

View file

@ -0,0 +1,188 @@
PROGRAM U !Reads a specification of a Turing machine, and executes it.
Careful! Reserves a symbol #0 to represent blank tape as a blank.
INTEGER MANY,FIRST,LAST !Some sizes must be decided upon.
PARAMETER (MANY = 66, FIRST = 1, LAST = 666) !These should do.
INTEGER HERE(MANY)
CHARACTER*1 MARK(MANY) !The transition table.
INTEGER*1 MOVE(MANY) !Three related arrays.
CHARACTER*1 NEXT(MANY) !All with the same indexing.
CHARACTER*1 TAPE(FIRST:LAST)!Notionally, no final bound, in both directions - a potential infinity..
INTEGER STATE !Execution starts with state 1.
INTEGER HEAD !And the tape read/write head at position 1.
INTEGER STEP !And we might as well keep count.
INTEGER OFFSET !An affine shift.
INTEGER NSTATE !Counts can be helpful.
INTEGER NSYMBOL !The count of recognised symbols.
INTEGER S,S1 !Symbol numbers.
CHARACTER*1 RS,WS !Input scanning: read symbol, write symbol.
CHARACTER*1 SYMBOL(0:MANY) !I reserve SYMBOL(0).
CHARACTER*(MANY) SYMBOLS !Up to 255, for single character variables.
EQUIVALENCE (SYMBOL(1),SYMBOLS) !Individually or collectively.
INTEGER I,J,K,L,IT !Assistants.
INTEGER LONG !Now for some text scanning.
PARAMETER (LONG = 80) !This should suffice.
CHARACTER*(LONG) ALINE !A scratchpad.
REAL T0,T1 !Some CPU time attempts.
INTEGER KBD,MSG,INF !Some I/O unit numbers.
KBD = 5 !Standard input.
MSG = 6 !Standard output
INF = 10 !Suitable for a disc file.
OPEN (INF,FILE = "TestAdd1.dat",ACTION="READ") !Go for one.
READ (INF,1) ALINE !The first line is to be a heding.
1 FORMAT (A) !Just plain text.
WRITE (MSG,2) ALINE !Reveal it.
2 FORMAT ("Turing machine simulation for... ",A) !Announce the plan.
READ (INF,*) SYMBOLS !Allows a quoted string.
NSYMBOL = LEN_TRIM(SYMBOLS) !How many symbols? (Trailing spaces will be lost)
WRITE (MSG,3) NSYMBOL,SYMBOLS(1:NSYMBOL) !They will be symbol number 0, 1, ..., NSYMBOL - 1.
3 FORMAT (I0," symbols: >",A,"<") !And this is their count.
IF (NSYMBOL.LE.1) STOP "Expect at least two symbols!"
SYMBOL(0) = " " !My special state meaning "never before seen".
NSYMBOL = NSYMBOL + 1 !So, one more is in actual use.
NSTATE = 0 !As for states, I haven't seen any.
MOVE = -66 !This should cause trouble and be noticed!
MARK = CHAR(0) !In case a state is omitted.
NEXT = CHAR(0) !Like, mention state seven, but omit mention of state six.
HERE = 0 !Clear the counts.
Collate the transition table.
10 READ (INF,*) STATE !Read this once, rather than for every transition.
IF (STATE.LE.0) GO TO 20 !Ah, finished.
WRITE (MSG,11) STATE !But they can come in any order.
NSTATE = MAX(STATE,NSTATE)!And I'd like to know how many.
11 FORMAT ("Entry: Read Write Move Next. For state ",I0) !Prepare a nice heading.
IF (STATE.LE.0) STOP "Positive STATE numbers only!" !It may not be followed.
IF (STATE*NSYMBOL.GT.MANY) STOP"My transition table is too small!" !But the value of STATE is shown.
DO S = 0,NSYMBOL - 1 !Initialise the transitions for STATE.
IT = STATE*NSYMBOL - S !Finger the one for S.
MARK(IT) = CHAR(S) !No change to what's under the head.
NEXT(IT) = CHAR(0) !And this stops the run.
END DO !Just in case a symbol's number is omitted.
DO S = 1,NSYMBOL - 1 !A transition for every symbol must be given or the read process will get out of step.
READ(INF,*) RS,WS,K,L !Read symbol, write symbol, move, next.
I = INDEX(SYMBOLS(1:NSYMBOL - 1),RS) !Convert the character to a symbol number.
J = INDEX(SYMBOLS(1:NSYMBOL - 1),WS) !To enable decorative glyphs, not just digits.
IF (I.LE.0) STOP "Unrecognised read symbol!" !This really should be more helpful.
IF (J.LE.0) STOP "Unrecognised write symbol!" !By reading into ALINE and showing it, etc.
IT = STATE*NSYMBOL - I !Locate the entry for the state x symbol pair.
MARK(IT) = CHAR(J) !The value to be written.
MOVE(IT) = K !The movement of the tape head.
NEXT(IT) = CHAR(L) !The next state.
IF (I.EQ.1) S1 = IT !This transition will be duplicated. SYMBOL(1) is for blank tape.
END DO !On to the next symbol's transition.
Copy SYMBOL(1)'s transition to the transition for the secret extra, SYMBOL(0).
IT = STATE*NSYMBOL !Finger the interpolated entry for SYMBOL(0).
MARK(IT) = MARK(S1) !Thus will SYMBOL(0), shown as a space, be overwritten.
MOVE(IT) = MOVE(S1) !And SYMBOL(0) treated
NEXT(IT) = NEXT(S1) !Exactly as if it were SYMBOL(1).
Cast forth the transition table for STATE, not mentioning SYMBOL(0) - but see label 911.
DO S = 1,NSYMBOL - 1 !Roll them out in the order as given in SYMBOL.
IT = STATE*NSYMBOL - S !But the entry number will be odd.
WRITE (ALINE,12) IT,SYMBOL(S), !The character's code value is irrelevant.
1 SYMBOL(ICHAR(MARK(IT))),MOVE(IT),ICHAR(NEXT(IT)) !Append the details just read.
12 FORMAT (I5,":",2X,'"',A1,'"',3X'"',A1,'"',I5,I5,I13) !Revealing the symbols, not their number.
IF (MOVE(IT).GT.0) ALINE(21:21) = "+" !I want a leading + for positive, not zero.
WRITE (MSG,1) ALINE(1:27) !The SP format code is unhelpful for zero.
END DO !Hopefully, I'm still in sync with the input.
GO TO 10 !Perhaps another state follows.
Chew tape. The initial state is some sequence of symbols, starting at TAPE(1).
20 TAPE = CHAR(0) !Set every cell to zero. Not blank.
OFFSET = 12 !Affine shift. The numerical value of HEAD is not seen.
READ (INF,1) ALINE !Get text, for the tape's initial state.
L = LEN_TRIM(ALINE) !Last non-blank. Flexible format this isn't.
DO I = 1,L !Step through cells 1 to L.
TAPE(I + OFFSET - 1) = CHAR(INDEX(SYMBOLS,ALINE(I:I))) !Character code to symbol number.
END DO !Rather than reading as I1.
CLOSE (INF) !Finished with the input, and not much checking either.
WRITE (MSG,*) !Take a breath.
Cast forth a heading..
WRITE (MSG,99) !Announce.
99 FORMAT ("Starts with State 1 and the tape head at 1.") !Positioned for OFFSET = 12.
ALINE = " Step: Head State|Tape..." !Prepare a heading for the trace.
L = 18 + OFFSET*2 !Locate the start position.
ALINE(L - 1:L + 1) = "<H>"!No underlining, no overprinting, no colour (neither background nor foreground). Sigh.
WRITE (MSG,1) ALINE !Take that!
CALL CPU_TIME(T0) !Start the clock.
HEAD = OFFSET !This is counted as position one.
STATE = 1 !The initial state.
STEP = 0 !No steps yet.
Chase through the transitions. Could check that HEAD is within bounds FIRST:LAST.
100 IF (STEP.GE.200) GO TO 200 !Perhaps an extended campaign.
STEP = STEP + 1 !Otherwise, here we go.
DO I = 1,LONG/2 !Scan TAPE(1:LONG/2).
IT = 2*I - 1 !Allowing two positions each.
ALINE(IT:IT) = " " !So a leading space.
ALINE(IT + 1:IT + 1) = SYMBOL(ICHAR(TAPE(I))) !And the indicated symbol.
END DO !On to the enxt.
I = HEAD*2 !The head's location in the display span.
IF (I.GT.1 .AND. I.LT.LONG) THEN !Within range?
IF (ALINE(I:I).EQ.SYMBOL(0)) ALINE(I:I) = SYMBOL(1) !Yes. Am I looking at a new cell?
ALINE(I - 1:I - 1) = "<" !Bracket the head's cell.
ALINE(I + 1:I + 1) = ">" !In ALINE.
END IF !So much for showing the head's position.
WRITE (MSG,102) STEP,HEAD - OFFSET + 1,STATE,ALINE !Splot the state.
102 FORMAT (I5,":",I5,I6,"|",A) !Aligns with FORMAT 99.
I = STATE*NSYMBOL - ICHAR(TAPE(HEAD)) !For this STATE and the symbol under TAPE(HEAD)
HERE(I) = HERE(I) + 1 !Count my visits.
TAPE(HEAD) = MARK(I) !Place the new symbol.
HEAD = HEAD + MOVE(I) !Move the head.
IF (HEAD.LT.FIRST .OR. HEAD.GT.LAST) GO TO 110 !Check the bounds.
STATE = ICHAR(NEXT(I)) !The new state.
IF (STATE.GT.0) GO TO 100 !Go to it.
Cease.
I = HEAD*2 !Locate HEAD within ALINE.
IF (I.GT.1 .AND. I.LT.LONG) ALINE(I:I) = SYMBOL(ICHAR(TAPE(HEAD))) !The only change.
WRITE (MSG,103) HEAD - OFFSET + 1,STATE,ALINE !Show.
103 FORMAT ("HALT!",I6,I6,"|",A) !But, no step count to start with. See FORMAT 102.
GO TO 900 !Done.
Can't continue! Insufficient tape, alas.
110 WRITE (MSG,*) "Insufficient tape!" !Oh dear.
GO TO 900 !Give in.
Change into high gear: no trace and no test thereof neither.
200 STEP = STEP + 1 !So, advance.
IF (MOD(STEP,10000000).EQ.0) WRITE (MSG,201) STEP !Ah, still some timewasting.
201 FORMAT ("Step ",I0) !No screen action is rather discouraging.
I = STATE*NSYMBOL - ICHAR(TAPE(HEAD)) !Index the transition.
HERE(I) = HERE(I) + 1 !Another visit.
TAPE(HEAD) = MARK(I) !Do it. Possibly not changing the symbol.
HEAD = HEAD + MOVE(I) !Possibly not moving the head.
IF (HEAD.LT.FIRST .OR. HEAD.GT.LAST) GO TO 110 !But checking the bounds just in case.
STATE = ICHAR(NEXT(I)) !Hopefully, something has changed!
IF (STATE.GT.0) GO TO 200 !Otherwise, we might loop forever...
Closedown.
900 CALL CPU_TIME(T1) !Where did it all go?
WRITE (MSG,901) STEP,STATE !Announce the ending.
901 FORMAT ("After step ",I0,", state = ",I0,".") !Thus.
DO I = FIRST,LAST !Scan the tape.
IF (ICHAR(TAPE(I)).NE.0) EXIT !This is the whole point of SYMBOL(0).
END DO !So that the bounds
DO J = LAST,FIRST,-1 !Of tape access
IF (ICHAR(TAPE(J)).NE.0) EXIT !(and placement of the initial state)
END DO !Can be found without tedious ongoing MIN and MAX.
WRITE (MSG,902) HEAD - OFFSET + 1, !Tediously,
1 I - OFFSET + 1, !Reverse the offset
2 J - OFFSET + 1 !So as to seem that HEAD = 1, to start with.
902 FORMAT ("The head is at position ",I0, !Now announce the results.
1 " and wandered over ",I0," to ",I0) !This will affect the dimension chosen for TAPE.
T1 = T1 - T0 !Some time may have been accurately measured.
IF (T1.GT.0.1) WRITE (MSG,903) T1 !And this may be sort of correct.
903 FORMAT ("CPU time",F9.3) !Though distinct from elapsed time.
Curious about the usage of the transition table?
910 WRITE (MSG,911) !Possibly not,
911 FORMAT (/,35X,"Usage.") !But here it comes.
DO STATE = 1,NSTATE !For every state
WRITE (MSG,11) STATE !Name the state, as before.
DO S = 0,NSYMBOL - 1 !But this time, roll every symbol.
IT = STATE*NSYMBOL - S !Including my "secret" symbol.
WRITE (ALINE,12) IT,SYMBOL(S), !The same sequence,
1 SYMBOL(ICHAR(MARK(IT))),MOVE(IT),ICHAR(NEXT(IT)),HERE(IT) !But with an addendum here.
IF (MOVE(IT).GT.0) ALINE(21:21) = "+" !SIGN(i,i) gives -1, 0, +1 but -60 for -60.
WRITE (MSG,1) ALINE(1:40) !When what I want is -1. SIGN(1,i) doesn't give zero.
END DO !On to the next symbol in the order as supplied.
END DO !And the next state, in numbers order.
END !That was fun.

View file

@ -0,0 +1,45 @@
function tm(d,s,e,i,b,t,... r) {
document.write(d, '<br>')
if (i<0||i>=t.length) return
write('*',s,i,t=t.split(''))
var p={}; r.forEach(e=>((s,r,w,m,n)=>{p[s+'.'+r]={w,n,m:[0,1,-1][1+'RL'.indexOf(m)]}})(... e.split(/[ .:,]+/)))
for (var n=1; s!=e; n+=1) {
with (p[s+'.'+t[i]]) t[i]=w,s=n,i+=m
if (i==-1) i=0,t.unshift(b)
else if (i==t.length) t[i]=b
write(n,s,i,t)
}
document.write('<br>')
function write(n, s, i, t) {
t = t.join('')
t = t.substring(0,i) + '<u>' + t.charAt(i) + '</u>' + t.substr(i+1)
document.write((' '+n).slice(-3).replace(/ /g,'&nbsp;'), ': ', s, ' [', t.replace(b,'&nbsp;','g'), ']', '<br>')
}
}
tm( 'Unary incrementer',
// s e i b t
'a', 'h', 0, 'B', '111',
// s.r: w, m, n
'a.1: 1, L, a',
'a.B: 1, S, h'
)
tm( 'Unary adder',
1, 0, 0, '0', '1110111',
'1.1: 0, R, 2', // write 0 rigth goto 2
'2.0: 0, S, 0', // if (0) halt
'2.1: 0, R, 3', // write 0 rigth goto 3
'3.1: 1, R, 3', // while (1) rigth
'3.0: 1, S, 0', // write 1 halt
)
tm( 'Three-state busy beaver',
1, 0, 0, '0', '0',
'1.0: 1, R, 2',
'1.1: 1, R, 0',
'2.0: 0, R, 3',
'2.1: 1, R, 2',
'3.0: 1, L, 3',
'3.1: 1, L, 1'
)

View file

@ -0,0 +1,84 @@
-- Machine definitions
local incrementer = {
name = "Simple incrementer",
initState = "q0",
endState = "qf",
blank = "B",
rules = {
{"q0", "1", "1", "right", "q0"},
{"q0", "B", "1", "stay", "qf"}
}
}
local threeStateBB = {
name = "Three-state busy beaver",
initState = "a",
endState = "halt",
blank = "0",
rules = {
{"a", "0", "1", "right", "b"},
{"a", "1", "1", "left", "c"},
{"b", "0", "1", "left", "a"},
{"b", "1", "1", "right", "b"},
{"c", "0", "1", "left", "b"},
{"c", "1", "1", "stay", "halt"}
}
}
local fiveStateBB = {
name = "Five-state busy beaver",
initState = "A",
endState = "H",
blank = "0",
rules = {
{"A", "0", "1", "right", "B"},
{"A", "1", "1", "left", "C"},
{"B", "0", "1", "right", "C"},
{"B", "1", "1", "right", "B"},
{"C", "0", "1", "right", "D"},
{"C", "1", "0", "left", "E"},
{"D", "0", "1", "left", "A"},
{"D", "1", "1", "left", "D"},
{"E", "0", "1", "stay", "H"},
{"E", "1", "0", "left", "A"}
}
}
-- Display a representation of the tape and machine state on the screen
function show (state, headPos, tape)
local leftEdge = 1
while tape[leftEdge - 1] do leftEdge = leftEdge - 1 end
io.write(" " .. state .. "\t| ")
for pos = leftEdge, #tape do
if pos == headPos then io.write("[" .. tape[pos] .. "] ") else io.write(" " .. tape[pos] .. " ") end
end
print()
end
-- Simulate a turing machine
function UTM (machine, tape, countOnly)
local state, headPos, counter = machine.initState, 1, 0
print("\n\n" .. machine.name)
print(string.rep("=", #machine.name) .. "\n")
if not countOnly then print(" State", "| Tape [head]\n---------------------") end
repeat
if not tape[headPos] then tape[headPos] = machine.blank end
if not countOnly then show(state, headPos, tape) end
for _, rule in ipairs(machine.rules) do
if rule[1] == state and rule[2] == tape[headPos] then
tape[headPos] = rule[3]
if rule[4] == "left" then headPos = headPos - 1 end
if rule[4] == "right" then headPos = headPos + 1 end
state = rule[5]
break
end
end
counter = counter + 1
until state == machine.endState
if countOnly then print("Steps taken: " .. counter) else show(state, headPos, tape) end
end
-- Main procedure
UTM(incrementer, {"1", "1", "1"})
UTM(threeStateBB, {})
UTM(fiveStateBB, {}, "countOnly")

View file

@ -0,0 +1,373 @@
;; "A Turing Turtle": a Turing Machine implemented in NetLogo
;; by Dan Dewey 1/16/2016
;;
;; This NetLogo code implements a Turing Machine, see, e.g.,
;; http://en.wikipedia.org/wiki/Turing_machine
;; The Turing machine fits nicely into the NetLogo paradigm in which
;; there are agents (aka the turtles), that move around
;; in a world of "patches" (2D cells).
;; Here, a single agent represents the Turing machine read/write head
;; and the patches represent the Turing tape values via their colors.
;; The 2D array of patches is treated as a single long 1D tape in an
;; obvious way.
;; This program is presented as a NetLogo example on the page:
;; http://rosettacode.org/wiki/Universal_Turing_machine
;; This file may be larger than others on that page, note however
;; that I include many comments in the code and I have made no
;; effort to 'condense' the code, prefering clarity over compactness.
;; A demo and discussion of this program is on the web page:
;; http://sites.google.com/site/dan3deweyscspaimsportfolio/extra-turing-machine
;; The Copy example machine was taken from:
;; http://en.wikipedia.org/wiki/Turing_machine_examples
;; The "Busy Beaver" machines encoded below were taken from:
;; http://www.logique.jussieu.fr/~michel/ha.html
;; The implementation here allows 3 symbols (blank, 0, 1) on the tape
;; and 3 head motions (left, stay, right).
;; The 2D world is nominally set to be 29x29, going from (-14,-14) to
;; (14,14) from lower left to upper right and with (0,0) at the center.
;; This gives a total Turing tape length of 29^2 = 841 cells, sufficient for the
;; "Lazy" Beaver 5,2 example.
;; Since the max-pxcor variable is used in the code below (as opposed to
;; a hard-coded number), the effective tape size can be changed by
;; changing the size of the 2D world with the Settings... button on the interface.
;; The "Info" tab of the NetLogo interface contains some further comments.
;; - - - - - - -
;; - - - - - - - - - - - Global/Agent variables
;; These three 2D arrays (lists of lists) encode the Turing Machine rules:
;; WhatToWrite: -1 (Blank), 0, 1
;; HowToMove: -1 (left), 0(stay), 1 (right)
;; NextState: 0 to N-1, negative value goes to a halt state.
;; The above are a function of the current state and the current tape (patch) value.
;; MachineState is used by the turtle to pass the current state of the Turing machine
;; (or the halt code) to the observer.
globals [ WhatToWrite HowToMove NextState MachineState
;; some other golobals of secondary importance...
;; set different patch colors to record the Turing tape values
BlankColor ZeroColor OneColor
;; a delay constant to slow down the operation
RealTimePerTick ]
;; We'll have one turtle which is the Turing machine read/write head
;; it will keep track of the current Turing state in its own MyState value
turtles-own [ MyState ]
;; - - - - - - - - - - -
to Setup ;; sets up the world
clear-all ;; clears the world first
;; Try to not have (too many) ad hoc numbers in the code,
;; collect and set various values here especially if they might be used in multiple places:
;; The colors for Blank, Zero and One : (user can can change as desired)
set BlankColor 2 ;; dark gray
set OneColor green
set ZeroColor red
;; slow it down for the humans to watch
set RealTimePerTick 0.2 ;; have simulation go at nice realtime speed
create-turtles 1 ;; create the one Turing turtle
[ ;; set default parameters
set size 2 ;; set a nominal size
set color yellow ;; color of border
;; set the starting location, some Turing programs will adjust this if needed:
setxy 0 0 ;; -1 * max-pxcor -1 * max-pxcor
set shape "square2empty" ;; edited version of "square 2" to have clear in middle
;; set the starting state - always 0
set MyState 0
set MachineState 0 ;; the turtle will update this global value from now on
]
;; Define the Turing machine rules with 2D lists.
;; Based on the selection made on interface panel, setting the string Turing_Program_Selection.
;; This routine has all the Turing 'programs' in it - it's at the very bottom of this file.
LoadTuringProgram
;; the environment, e.g. the Turing tape
ask patches
[
;; all patches are set to the blank color
set pcolor BlankColor
]
;; keep track of time; each tick is a Turing step
reset-ticks
end
;; - - - - - - - - - - - - - - - -
to Go ;; this repeatedly does steps
;; The turtle does the main work
ask turtles
[
DoOneStep
wait RealTimePerTick
]
tick
;; The Turing turtle will die if it tries to go beyond the cells,
;; in that case (no turtles left) we'll stop.
;; Also stop if the MachineState has been set to a negative number (a halt state).
if ((count turtles = 0) or (MachineState < 0))
[ stop ]
end
to DoOneStep
;; have the turtle do one Turing step
;; First, 'read the tape', i.e., based on the patch color here:
let tapeValue GetTapeValue
;; using the tapeValue and MyState, get the desired actions here:
;; (the item commands extract the appropriate value from the list-of-lists)
let myWrite item (tapeValue + 1) (item MyState WhatToWrite)
let myMove item (tapeValue + 1) (item MyState HowToMove)
let myNextState item (tapeValue + 1) (item MyState NextState)
;; Write to the tape as appropriate
SetTapeValue myWrite
;; Move as appropriate
if (myMove = 1) [MoveForward]
if (myMove = -1) [MoveBackward]
;; Go to the next state; check if it is a halt state.
;; Update the global MachineState value
set MachineState myNextState
ifelse (myNextState < 0)
[
;; It's a halt state. The negative MachineState will signal the stop.
;; Go back to the starting state so it can be re-run if desired.
set MyState 0]
[
;; Not a halt state, so change to the desired next state
set MyState myNextState
]
end
to MoveForward
;; move the turtle forward one cell, including line wrapping.
set heading 90
ifelse (xcor = max-pxcor)
[set xcor -1 * max-pxcor
;; and go up a row if possible... otherwise die
ifelse ycor = max-pxcor
[ die ] ;; tape too short - a somewhat crude end of things ;-)
[set ycor ycor + 1]
]
[jump 1]
end
to MoveBackward
;; move the turtle backward one cell, including line-wrapping.
set heading -90
ifelse (xcor = -1 * max-pxcor)
[
set xcor max-pxcor
;; and go down a row... or die
ifelse ycor = -1 * max-pxcor
[ die ] ;; tape too short - a somewhat crude end of things ;-)
[set ycor ycor - 1]
]
[jump 1]
end
to-report GetTapeValue
;; report the tape color equivalent value
if (pcolor = ZeroColor) [report 0]
if (pcolor = OneColor) [report 1]
report -1
end
to SetTapeValue [ value ]
;; write the appropriate color on the tape
ifelse (value = 1)
[set pcolor OneColor]
[ ifelse (value = 0)
[set pcolor ZeroColor][set pcolor BlankColor]]
end
;; - - - - - OK, here are the data for the various Turing programs...
;; Note that besdes settting the rules (array values) these sections can also
;; include commands to clear the tape, position the r/w head, adjust wait time, etc.
to LoadTuringProgram
;; A template of the rules structure: a list of lists
;; E.g. values are given for States 0 to 4, when looking at Blank, Zero, One:
;; For 2-symbol machines use Blank(-1) and One(1) and ignore the middle values (never see zero).
;; Normal Halt will be state -1, the -9 default shows an unexpected halt.
;; state 0 state 1 state 2 state 3 state 4
set WhatToWrite (list (list -1 0 1) (list -1 0 1) (list -1 0 1) (list -1 0 1) (list -1 0 1) )
set HowToMove (list (list 0 0 0) (list 0 0 0) (list 0 0 0) (list 0 0 0) (list 0 0 0) )
set NextState(list (list -9 -9 -9) (list -9 -9 -9) (list -9 -9 -9) (list -9 -9 -9) (list -9 -9 -9) )
;; Fill the rules based on the selected case
if (Turing_Program_Selection = "Simple Incrementor")
[
;; simple Incrementor - this is from the RosettaCode Universal Turing Machine page - very simple!
set WhatToWrite (list (list 1 0 1) )
set HowToMove (list (list 0 0 1) )
set NextState (list (list -1 -9 0) )
]
;; Fill the rules based on the selected case
if (Turing_Program_Selection = "Incrementor w/Return")
[
;; modified Incrementor: it returns to the first 1 on the left.
;; This version allows the "Copy Ones to right" program to directly follow it.
;; move right append one back to beginning
set WhatToWrite (list (list -1 0 1) (list 1 0 1) (list -1 0 1) )
set HowToMove (list (list 1 0 1) (list 0 0 1) (list 1 0 -1) )
set NextState (list (list 1 -9 1) (list 2 -9 1) (list -1 -9 2) )
]
;; Fill the rules based on the selected case
if (Turing_Program_Selection = "Copy Ones to right")
[
;; "Copy" from Wiki "Turing machine examples" page; slight mod so that it ends on first 1
;; of the copy allowing Copy to be re-executed to create another copy.
;; Has 5 states and uses Blank and 1 to make a copy of a string of ones;
;; this can be run after runs of the "Incrementor w/Return".
;; state 0 state 1 state 2 state 3 state 4
set WhatToWrite (list (list -1 0 -1) (list -1 0 1) (list 1 0 1) (list -1 0 1) (list 1 0 1) )
set HowToMove (list (list 1 0 1) (list 1 0 1) (list -1 0 1) (list -1 0 -1) (list 1 0 -1) )
set NextState (list (list -1 -9 1) (list 2 -9 1) (list 3 -9 2) (list 4 -9 3) (list 0 -9 4) )
]
;; Fill the rules based on the selected case
if (Turing_Program_Selection = "Binary Counter")
[
;; Count in binary - can start on a blank space.
;; States: start carry-1 back-to-beginning
set WhatToWrite (list (list 1 1 0) (list 1 1 0) (list -1 0 1) )
set HowToMove (list (list 0 0 -1) (list 0 0 -1) (list -1 1 1) )
set NextState (list (list -1 -1 1) (list 2 2 1) (list -1 2 2) )
;; Select line above from these two:
;; can either count by 1 each time it is run:
;; set NextState (list (list -1 -1 1) (list 2 2 1) (list -1 2 2) )
;; or count forever once started:
;; set NextState (list (list 0 0 1) (list 2 2 1) (list 0 2 2) )
set RealTimePerTick 0.2
]
if (Turing_Program_Selection = "Busy-Beaver 3-State, 2-Sym")
[
;; from the RosettaCode.org Universal Turing Machine page
;; state name: a b c
set WhatToWrite (list (list 1 0 1) (list 1 0 1) (list 1 0 1) (list -1 0 1) (list -1 0 1) )
set HowToMove (list (list 1 0 -1) (list -1 0 1) (list -1 0 0) (list 0 0 0) (list 0 0 0) )
set NextState (list (list 1 -9 2) (list 0 -9 1) (list 1 -9 -1) (list -9 -9 -9) (list -9 -9 -9) )
;; Clear the tape
ask Patches [set pcolor BlankColor]
]
;; should output 13 ones and take 107 steps to do it...
if (Turing_Program_Selection = "Busy-Beaver 4-State, 2-Sym")
[
;; from the RosettaCode.org Universal Turing Machine page
;; state name: A B C D
set WhatToWrite (list (list 1 0 1) (list 1 0 -1) (list 1 0 1) (list 1 0 -1) (list -1 0 1) )
set HowToMove (list (list 1 0 -1) (list -1 0 -1) (list 1 0 -1) (list 1 0 1) (list 0 0 0) )
set NextState (list (list 1 -9 1) (list 0 -9 2) (list -1 -9 3) (list 3 -9 0) (list -9 -9 -9) )
;; Clear the tape
ask Patches [set pcolor BlankColor]
]
;; This takes 38 steps to write 9 ones/zeroes
if (Turing_Program_Selection = "Busy-Beaver 2-State, 3-Sym")
[
;; A B
set WhatToWrite (list (list 0 1 0) (list 1 1 0) (list -1 0 1) (list -1 0 1) (list -1 0 1) )
set HowToMove (list (list 1 -1 1) (list -1 1 -1) (list 0 0 0) (list 0 0 0) (list 0 0 0) )
set NextState(list (list 1 1 -1) (list 0 1 1) (list -9 -9 -9) (list -9 -9 -9) (list -9 -9 -9) )
;; Clear the tape
ask Patches [set pcolor BlankColor]
]
;; This only makes 501 ones and stops after 134,467 steps -- it does do that !!!
if (Turing_Program_Selection = "Lazy-Beaver 5-State, 2-Sym")
[
;; from the RosettaCode.org Universal Turing Machine page
;; state name: A0 B1 C2 D3 E4
set WhatToWrite (list (list 1 0 -1) (list 1 0 1) (list 1 0 -1) (list -1 0 1) (list 1 0 1) )
set HowToMove (list (list 1 0 -1) (list 1 0 1) (list -1 0 1) (list 1 0 1) (list -1 0 1) )
set NextState (list (list 1 -9 2) (list 2 -9 3) (list 0 -9 1) (list 4 -9 -1) (list 2 -9 0) )
;; Clear the tape
ask Patches [set pcolor BlankColor]
;; Looks like it goes much more forward than back on the tape
;; so start the head just a row from the bottom:
ask turtles [setxy 0 -1 * max-pxcor + 1]
;; and go faster
set RealTimePerTick 0.02
]
;; The rest have large outputs and run for a long time, so I haven't confirmed
;; that they work as advertised...
;; This is the 5,2 record holder: 4098 ones in 47,176,870 steps.
;; With max-pxcor of 14 and offset r/w head start (below), this will
;; run off the tape at about 150,000+steps...
if (Turing_Program_Selection = "Busy-Beaver 5-State, 2-Sym")
[
;; from the RosettaCode.org Universal Turing Machine page
;; state name: A B C D E
set WhatToWrite (list (list 1 0 1) (list 1 0 1) (list 1 0 -1) (list 1 0 1) (list 1 0 -1) )
set HowToMove (list (list 1 0 -1) (list 1 0 1) (list 1 0 -1) (list -1 0 -1) (list 1 0 -1) )
set NextState (list (list 1 -9 2) (list 2 -9 1) (list 3 -9 4) (list 0 -9 3) (list -1 -9 0) )
;; Clear the tape
ask Patches [set pcolor BlankColor]
;; Writes more backward than forward, so start a few rows from the top:
ask turtles [setxy 0 max-pxcor - 3]
;; and go faster
set RealTimePerTick 0.02
]
if (Turing_Program_Selection = "Lazy-Beaver 3-State, 3-Sym")
[
;; This should write 5600 ones/zeros and take 29,403,894 steps.
;; Ran it to 175,000+ steps and only covered 1/2 of the cells (w/max-pxcor = 14)...
;; state name: A B C
set WhatToWrite (list (list 0 1 0) (list 1 -1 0) (list 0 1 0) (list -1 0 1) (list -1 0 1) )
set HowToMove (list (list 1 1 -1) (list -1 1 1) (list 1 -1 1) (list 0 0 0) (list 0 0 0) )
set NextState (list (list 1 0 0) (list 2 2 1) (list -1 0 1) (list -9 -9 -9) (list -9 -9 -9) )
;; Clear the tape
ask Patches [set pcolor BlankColor]
;; It goes much more forward than back on the tape
;; so start the head just a row from the bottom:
ask turtles [setxy 0 -1 * max-pxcor + 1]
;; and go faster
set RealTimePerTick 0.02
]
if (Turing_Program_Selection = "Busy-Beaver 3-State, 3-Sym")
[
;; This should write 374,676,383 ones/zeros and take 119,112,334,170,342,540 (!!!) steps.
;; Rn it to ~ 175,000 steps covering about 2/3 of the max-pxcor=14 cells.
;; state name: A B C
set WhatToWrite (list (list 0 1 0) (list -1 1 0) (list 0 0 0) (list -1 0 1) (list -1 0 1) )
set HowToMove (list (list 1 -1 -1) (list -1 1 -1) (list 1 1 1) (list 0 0 0) (list 0 0 0) )
set NextState (list (list 1 0 2) (list 0 1 1) (list -1 0 2) (list -9 -9 -9) (list -9 -9 -9) )
;; Clear the tape
ask Patches [set pcolor BlankColor]
;; Writes more backward than forward, so start a rowish from the top:
ask turtles [setxy 0 max-pxcor - 1]
;; and go faster
set RealTimePerTick 0.02
]
;; in all cases reset the machine state to 0:
ask turtles [set MyState 0]
set MachineState 0
;; and the ticks
reset-ticks
end

View file

@ -1,41 +1,45 @@
/*REXX pgm executes a Turing machine based on initial state, tape, rules*/
state = 'q0' /*initial Turing machine state. */
term = 'qf' /*a state that is used for halt. */
blank = 'B' /*this character is a true blank.*/
call turing_rule 'q0 1 1 right q0' /*define a rule for the machine. */
call turing_rule 'q0 B 1 stay qf' /* " " " " " " */
call turing_init 1 1 1 /*initialize tape to string(s). */
call turing_machine /*go invoke the Turning machine. */
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────TURING_MACHINE subroutine───────────*/
turing_machine: !=1; bot=1; top=1 /*start at the tape location 1. */
say /*might as well show a blank line*/
do cycle=1 until state==term /*do Turing machine instructions.*/
do k=1 for rules /*process the Turning mach. rules*/
parse var rule.k rState rTape rWrite rMove rNext . /*pick pieces*/
if state\==rState | @.!\==rTape then iterate /*wrong rule?*/
@.!=rWrite /*right rule; write it ──► tape.*/
if rMove== 'left' then !=!-1 /*Move left? Then subtract one.*/
if rMove=='right' then !=!+1 /*Move right? Then add one.*/
bot=min(bot,!); top=max(top,!) /*find the tape bottom and top.*/
state=rNext /*use this for the next state. */
iterate cycle /*go process another instruction.*/
end /*k*/
say '***error!*** unknown state:' state; leave /*oops.*/
end /*cycle*/
$= /*start with empty string (tape).*/
do t=bot to top; _=@.t; if _==blank then _=' ' /*translate?*/
$=$ || pad || _ /*build chr by chr, maybe pad it.*/
end /*t*/ /* [↑] build the tape's contents.*/
if $='' then $= "[tape is blank.]" /*make an empty tape visible.*/
say 'Turning machine used' rules "rules in" cycle 'cycles, tape is:' $
return
/*──────────────────────────────────TURING_INIT subroutine──────────────*/
turing_init: @.=blank; parse arg x
do j=1 for words(x); @.j=word(x,j); end /*j*/
return
/*──────────────────────────────────TURING_RULE subroutine──────────────*/
turing_rule: if symbol('RULES')=="LIT" then rules=0; rules=rules+1
pad=left('',length(word(arg(1),2))\==1) /*used if any symbol's length>1.*/
rule.rules=arg(1); say right('rule' rules,20) "═══►" rule.rules
return
/*REXX program executes a Turing machine based on initial state, tape, and rules. */
state = 'q0' /*the initial Turing machine state. */
term = 'qf' /*a state that is used for a halt. */
blank = 'B' /*this character is a "true" blank. */
call Turing_rule 'q0 1 1 right q0' /*define a rule for the Turing machine.*/
call Turing_rule 'q0 B 1 stay qf' /* " " " " " " " */
call Turing_init 1 1 1 /*initialize the tape to some string(s)*/
call TM /*go and invoke the Turning machine. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
TM: !=1; bot=1; top=1; @er= '***error***' /*start at the tape location 1. */
say /*might as well display a blank line. */
do cycle=1 until state==term /*process Turing machine instructions.*/
do k=1 for rules /* " " " rules. */
parse var rule.k rState rTape rWrite rMove rNext . /*pick pieces. */
if state\==rState | @.!\==rTape then iterate /*wrong rule ? */
@.!=rWrite /*right rule; write it ───► the tape. */
if rMove== 'left' then !=!-1 /*Are we moving left? Then subtract 1*/
if rMove=='right' then !=!+1 /* " " " right? " add 1*/
bot=min(bot, !); top=max(top, !) /*find the tape bottom and top. */
state=rNext /*use this for the next state. */
iterate cycle /*go process another TM instruction. */
end /*k*/
say @er 'unknown state:' state; leave /*oops, we have an unknown state error.*/
end /*cycle*/
$= /*start with empty string (the tape). */
do t=bot to top; _=@.t
if _==blank then _=' ' /*do we need to translate a true blank?*/
$=$ || pad || _ /*construct char by char, maybe pad it.*/
end /*t*/ /* [↑] construct the tape's contents.*/
L=length($)
if L==0 then $= "[tape is blank.]" /*make an empty tape visible to user.*/
if L>1000 then $=left($, 1000) ... /*truncate tape to 1k bytes, append ···*/
say "tape's contents:" $ /*show the tape's contents (or 1st 1k).*/
say "tape's length: " L /* " " " length. */
say 'Turning machine used ' rules " rules in " cycle ' cycles.'
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
Turing_init: @.=blank; parse arg x; do j=1 for words(x); @.j=word(x,j); end /*j*/
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
Turing_rule: if symbol('RULES')=="LIT" then rules=0; rules=rules+1
pad=left('', length( word( arg(1),2 ) ) \==1 ) /*padding for rule*/
rule.rules=arg(1); say right('rule' rules, 20) "═══►" rule.rules
return

View file

@ -1,15 +1,15 @@
/*REXX pgm executes a Turing machine based on initial state, tape, rules*/
state = 'a' /*initial Turing machine state. */
term = 'halt' /*a state that is used for halt. */
blank = 0 /*this character is a true blank.*/
call turing_rule 'a 0 1 right b' /*define a rule for the machine. */
call turing_rule 'a 1 1 left c' /* " " " " " " */
call turing_rule 'b 0 1 left a' /* " " " " " " */
call turing_rule 'b 1 1 right b' /* " " " " " " */
call turing_rule 'c 0 1 left b' /* " " " " " " */
call turing_rule 'c 1 1 stay halt' /* " " " " " " */
call turing_init /*initialize tape to string(s). */
call turing_machine /*go invoke the Turning machine. */
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────TURING_MACHINE subroutine───────────*/
turing_machine
/*REXX program executes a Turing machine based on initial state, tape, and rules. */
state = 'a' /*the initial Turing machine state. */
term = 'halt' /*a state that is used for a halt. */
blank = 0 /*this character is a "true" blank. */
call Turing_rule 'a 0 1 right b' /*define a rule for the Turing machine.*/
call Turing_rule 'a 1 1 left c' /* " " " " " " " */
call Turing_rule 'b 0 1 left a' /* " " " " " " " */
call Turing_rule 'b 1 1 right b' /* " " " " " " " */
call Turing_rule 'c 0 1 left b' /* " " " " " " " */
call Turing_rule 'c 1 1 stay halt' /* " " " " " " " */
call Turing_init /*initialize the tape to some string(s)*/
call TM /*go and invoke the Turning machine. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
TM:

View file

@ -1,19 +1,19 @@
/*REXX pgm executes a Turing machine based on initial state, tape, rules*/
state = 'A' /*initial Turing machine state. */
term = 'H' /*a state that is used for halt. */
blank = 0 /*this character is a true blank.*/
call turing_rule 'A 0 1 right B' /*define a rule for the machine. */
call turing_rule 'A 1 1 left C' /* " " " " " " */
call turing_rule 'B 0 1 right C' /* " " " " " " */
call turing_rule 'B 1 1 right B' /* " " " " " " */
call turing_rule 'C 0 1 right D' /* " " " " " " */
call turing_rule 'C 1 1 left E' /* " " " " " " */
call turing_rule 'D 0 1 left A' /* " " " " " " */
call turing_rule 'D 1 1 left D' /* " " " " " " */
call turing_rule 'E 0 1 stay H' /* " " " " " " */
call turing_rule 'E 1 1 left A' /* " " " " " " */
call turing_init /*initialize tape to string(s). */
call turing_machine /*go invoke the Turning machine. */
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────TURING_MACHINE subroutine───────────*/
turing_machine
/*REXX program executes a Turing machine based on initial state, tape, and rules. */
state = 'A' /*initialize the Turing machine state.*/
term = 'H' /*a state that is used for the halt. */
blank = 0 /*this character is a "true" blank. */
call Turing_rule 'A 0 1 right B' /*define a rule for the Turing machine.*/
call Turing_rule 'A 1 1 left C' /* " " " " " " " */
call Turing_rule 'B 0 1 right C' /* " " " " " " " */
call Turing_rule 'B 1 1 right B' /* " " " " " " " */
call Turing_rule 'C 0 1 right D' /* " " " " " " " */
call Turing_rule 'C 1 0 left E' /* " " " " " " " */
call Turing_rule 'D 0 1 left A' /* " " " " " " " */
call Turing_rule 'D 1 1 left D' /* " " " " " " " */
call Turing_rule 'E 0 1 stay H' /* " " " " " " " */
call Turing_rule 'E 1 0 left A' /* " " " " " " " */
call Turing_init /*initialize the tape to some string(s)*/
call TM /*go and invoke the Turning machine. */
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
TM:

View file

@ -1,23 +1,23 @@
/*REXX pgm executes a Turing machine based on initial state, tape, rules*/
state = 'A' /*initial Turing machine state. */
term = 'halt' /*a state that is used for halt. */
blank = 0 /*this character is a true blank.*/
call turing_rule 'A 1 1 right A' /*define a rule for the machine. */
call turing_rule 'A 2 3 right B' /* " " " " " " */
call turing_rule 'A 0 0 left E' /* " " " " " " */
call turing_rule 'B 1 1 right B' /* " " " " " " */
call turing_rule 'B 2 2 right B' /* " " " " " " */
call turing_rule 'B 0 0 left C' /* " " " " " " */
call turing_rule 'C 1 2 left D' /* " " " " " " */
call turing_rule 'C 2 2 left C' /* " " " " " " */
call turing_rule 'C 3 2 left E' /* " " " " " " */
call turing_rule 'D 1 1 left D' /* " " " " " " */
call turing_rule 'D 2 2 left D' /* " " " " " " */
call turing_rule 'D 3 1 right A' /* " " " " " " */
call turing_rule 'E 1 1 left E' /* " " " " " " */
call turing_rule 'E 0 0 right halt' /* " " " " " " */
call turing_init 1 2 2 1 2 2 1 2 1 2 1 2 1 2 /*init. tape to string(s). */
call turing_machine /*go invoke the Turning machine. */
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────TURING_MACHINE subroutine───────────*/
turing_machine
/*REXX program executes a Turing machine based on initial state, tape, and rules. */
state = 'A' /*the initial Turing machine state. */
term = 'halt' /*a state that is used for the halt. */
blank = 0 /*this character is a "true" blank. */
call Turing_rule 'A 1 1 right A' /*define a rule for the Turing machine.*/
call Turing_rule 'A 2 3 right B' /* " " " " " " " */
call Turing_rule 'A 0 0 left E' /* " " " " " " " */
call Turing_rule 'B 1 1 right B' /* " " " " " " " */
call Turing_rule 'B 2 2 right B' /* " " " " " " " */
call Turing_rule 'B 0 0 left C' /* " " " " " " " */
call Turing_rule 'C 1 2 left D' /* " " " " " " " */
call Turing_rule 'C 2 2 left C' /* " " " " " " " */
call Turing_rule 'C 3 2 left E' /* " " " " " " " */
call Turing_rule 'D 1 1 left D' /* " " " " " " " */
call Turing_rule 'D 2 2 left D' /* " " " " " " " */
call Turing_rule 'D 3 1 right A' /* " " " " " " " */
call Turing_rule 'E 1 1 left E' /* " " " " " " " */
call Turing_rule 'E 0 0 right halt' /* " " " " " " " */
call Turing_init 1 2 2 1 2 2 1 2 1 2 1 2 1 2 /*initialize the tape to some string(s)*/
call TM /*go and invoke the Turning machine. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
TM: