Universal Turing machine: Difference between revisions
Content added Content deleted
(Updated to work with Nim 1.4: replaced “split” with “splitWhiteSpace”. Also other minor changes. Added output.) |
Not a robot (talk | contribs) (Add Cowgol) |
||
Line 1,858: | Line 1,858: | ||
10100100100100100100...</pre> |
10100100100100100100...</pre> |
||
=={{header|Cowgol}}== |
|||
<lang cowgol>include "cowgol.coh"; |
|||
include "strings.coh"; |
|||
include "malloc.coh"; |
|||
############################################################################### |
|||
########################## Turing machine definition ########################## |
|||
############################################################################### |
|||
typedef Symbol is uint8; # 256 symbols ought to be enough for everyone |
|||
const LEFT := 1; |
|||
const RIGHT := 2; |
|||
const STAY := 3; |
|||
typedef Action is int(LEFT, STAY); |
|||
# Linked list |
|||
record Linked is |
|||
next: [Linked]; |
|||
end record; |
|||
record DoublyLinked: Linked is |
|||
prev: [DoublyLinked]; |
|||
end record; |
|||
sub FreeLinked(r: [Linked]) is |
|||
while r != 0 as [Linked] loop |
|||
var v := r.next; |
|||
Free(r as [uint8]); |
|||
r := v; |
|||
end loop; |
|||
end sub; |
|||
sub FreeDoublyLinked(r: [DoublyLinked]) is |
|||
FreeLinked(r.next); |
|||
while r != 0 as [DoublyLinked] loop |
|||
var v := r.prev; |
|||
Free(r as [uint8]); |
|||
r := v; |
|||
end loop; |
|||
end sub; |
|||
# Turing machine |
|||
typedef Turing is [TuringR]; |
|||
record StateR: Linked is |
|||
tm: Turing; # turing machine this state belongs to |
|||
term: uint8; # whether state is terminating |
|||
end record; |
|||
typedef State is [StateR]; |
|||
record Cell: DoublyLinked is |
|||
sym: Symbol; |
|||
end record; |
|||
record RuleR: Linked is |
|||
instate: State; |
|||
insym: Symbol; |
|||
outsym: Symbol; |
|||
action: Action; |
|||
outstate: State; |
|||
end record; |
|||
typedef Rule is [RuleR]; |
|||
record TuringR is |
|||
states: State; |
|||
rules: Rule; |
|||
initial: State; |
|||
current: State; |
|||
blank: Symbol; |
|||
head: [Cell]; |
|||
end record; |
|||
sub MakeCell(): (c: [Cell]) is |
|||
c := Alloc(@bytesof Cell) as [Cell]; |
|||
MemZero(c as [uint8], @bytesof Cell); |
|||
end sub; |
|||
# Define a Turing machine |
|||
sub MakeTuring(blank: Symbol, init: [Symbol]): (t: Turing) is |
|||
t := Alloc(@bytesof TuringR) as Turing; |
|||
MemZero(t as [uint8], @bytesof TuringR); |
|||
t.blank := blank; |
|||
t.head := MakeCell(); |
|||
t.head.sym := blank; |
|||
var c := t.head; |
|||
var d: [Cell]; |
|||
while [init] != 0 loop |
|||
c.sym := [init]; |
|||
init := @next init; |
|||
if [init] == 0 then break; end if; |
|||
d := Alloc(@bytesof Cell) as [Cell]; |
|||
d.prev := c as [DoublyLinked]; |
|||
d.next := 0 as [Linked]; |
|||
c.next := d as [Linked]; |
|||
c := d; |
|||
end loop; |
|||
end sub; |
|||
# Add a state to a Turing machine |
|||
const T_NONE := 0; |
|||
const T_INIT := 1; |
|||
const T_HALT := 2; |
|||
sub MakeState(t: Turing, type: uint8): (s: State) is |
|||
s := Alloc(@bytesof StateR) as State; |
|||
s.tm := t; |
|||
s.next := t.states as [Linked]; |
|||
t.states := s; |
|||
if type & T_INIT != 0 then |
|||
t.initial := s; |
|||
t.current := s; |
|||
end if; |
|||
s.term := 0; |
|||
if type & T_HALT != 0 then |
|||
s.term := 1; |
|||
end if; |
|||
end sub; |
|||
# Add a rule to a Turing machine |
|||
sub MakeRule(t: Turing, |
|||
instate: State, |
|||
insym: Symbol, |
|||
outsym: Symbol, |
|||
action: Action, |
|||
outstate: State): (r: Rule) is |
|||
r := Alloc(@bytesof RuleR) as Rule; |
|||
r.instate := instate; |
|||
r.insym := insym; |
|||
r.outsym := outsym; |
|||
r.action := action; |
|||
r.outstate := outstate; |
|||
r.next := t.rules as [Linked]; |
|||
t.rules := r; |
|||
end sub; |
|||
# Free a Turing machine |
|||
sub FreeTuring(t: Turing) is |
|||
FreeDoublyLinked(t.head as [DoublyLinked]); |
|||
FreeLinked(t.states as [Linked]); |
|||
FreeLinked(t.rules as [Linked]); |
|||
Free(t as [uint8]); |
|||
end sub; |
|||
# Move the head |
|||
sub MoveHead(t: Turing, a: Action) is |
|||
var c: [Cell]; |
|||
case a is |
|||
when STAY: return; |
|||
when LEFT: |
|||
if t.head.prev == 0 as [DoublyLinked] then |
|||
c := Alloc(@bytesof Cell) as [Cell]; |
|||
c.prev := 0 as [DoublyLinked]; |
|||
c.next := t.head as [Linked]; |
|||
c.sym := t.blank; |
|||
t.head.prev := c as [DoublyLinked]; |
|||
end if; |
|||
t.head := t.head.prev as [Cell]; |
|||
return; |
|||
when RIGHT: |
|||
if t.head.next == 0 as [Linked] then |
|||
c := Alloc(@bytesof Cell) as [Cell]; |
|||
c.next := 0 as [Linked]; |
|||
c.prev := t.head as [DoublyLinked]; |
|||
c.sym := t.blank; |
|||
t.head.next := c as [Linked]; |
|||
end if; |
|||
t.head := t.head.next as [Cell]; |
|||
return; |
|||
when else: |
|||
print("Invalid action\n"); |
|||
ExitWithError(); |
|||
end case; |
|||
end sub; |
|||
# Step a Turing machine |
|||
sub Step(t: Turing): (halt: uint8) is |
|||
# If we're in a halt state, do nothing |
|||
if t.current.term != 0 then |
|||
halt := 1; |
|||
return; |
|||
end if; |
|||
var r := t.rules; |
|||
while r != 0 as Rule loop |
|||
# Check each rule to see if it matches the current configuration |
|||
if t.current == r.instate |
|||
and t.head.sym == r.insym then |
|||
# Found a match |
|||
t.head.sym := r.outsym; |
|||
MoveHead(t, r.action); |
|||
t.current := r.outstate; |
|||
halt := t.current.term; |
|||
return; |
|||
end if; |
|||
r := r.next as Rule; |
|||
end loop; |
|||
print("No valid rule!\n"); |
|||
ExitWithError(); |
|||
end sub; |
|||
# Run a Turing machine until it halts |
|||
sub Run(t: Turing) is |
|||
while Step(t) == 0 loop |
|||
end loop; |
|||
end sub; |
|||
# Print the touched part of the tape of a Turing machine |
|||
sub PrintTape(t: Turing, max: uint32) is |
|||
var c := t.head; |
|||
var len: uint32 := 0; |
|||
while c.prev != 0 as [DoublyLinked] loop |
|||
c := c.prev as [Cell]; |
|||
end loop; |
|||
while c != 0 as [Cell] loop |
|||
if len < max then |
|||
print_char(c.sym as uint8); |
|||
end if; |
|||
c := c.next as [Cell]; |
|||
len := len + 1; |
|||
end loop; |
|||
if len >= max then |
|||
print("... (total length: "); |
|||
print_i32(len); |
|||
print(")"); |
|||
end if; |
|||
end sub; |
|||
############################################################################### |
|||
######################## Turing machines from the task ######################## |
|||
############################################################################### |
|||
interface TuringFactory(): (t: Turing); |
|||
sub SimpleIncrementer implements TuringFactory is |
|||
var r: Rule; |
|||
t := MakeTuring('B', "111"); |
|||
var q0 := MakeState(t, T_INIT); |
|||
var qf := MakeState(t, T_HALT); |
|||
r := MakeRule(t, q0, '1', '1', RIGHT, q0); |
|||
r := MakeRule(t, q0, 'B', '1', STAY, qf); |
|||
end sub; |
|||
sub ThreeStateBeaver implements TuringFactory is |
|||
var r: Rule; |
|||
t := MakeTuring('0', ""); |
|||
var a := MakeState(t, T_INIT); |
|||
var b := MakeState(t, T_NONE); |
|||
var c := MakeState(t, T_NONE); |
|||
var halt := MakeState(t, T_HALT); |
|||
r := MakeRule(t, a, '0', '1', RIGHT, b); |
|||
r := MakeRule(t, a, '1', '1', LEFT, c); |
|||
r := MakeRule(t, b, '0', '1', LEFT, a); |
|||
r := MakeRule(t, b, '1', '1', RIGHT, b); |
|||
r := MakeRule(t, c, '0', '1', LEFT, b); |
|||
r := MakeRule(t, c, '1', '1', STAY, halt); |
|||
end sub; |
|||
sub FiveStateBeaver implements TuringFactory is |
|||
var r: Rule; |
|||
t := MakeTuring('0', ""); |
|||
var A := MakeState(t, T_INIT); |
|||
var B := MakeState(t, T_NONE); |
|||
var C := MakeState(t, T_NONE); |
|||
var D := MakeState(t, T_NONE); |
|||
var E := MakeState(t, T_NONE); |
|||
var H := MakeState(t, T_HALT); |
|||
r := MakeRule(t, A, '0', '1', RIGHT, B); |
|||
r := MakeRule(t, A, '1', '1', LEFT, C); |
|||
r := MakeRule(t, B, '0', '1', RIGHT, C); |
|||
r := MakeRule(t, B, '1', '1', RIGHT, B); |
|||
r := MakeRule(t, C, '0', '1', RIGHT, D); |
|||
r := MakeRule(t, C, '1', '0', LEFT, E); |
|||
r := MakeRule(t, D, '0', '1', LEFT, A); |
|||
r := MakeRule(t, D, '1', '1', LEFT, D); |
|||
r := MakeRule(t, E, '0', '1', STAY, H); |
|||
r := MakeRule(t, E, '1', '0', LEFT, A); |
|||
end sub; |
|||
record TF is |
|||
name: [uint8]; |
|||
tf: TuringFactory; |
|||
end record; |
|||
var machines: TF[] := { |
|||
{"Simple incrementer", SimpleIncrementer}, |
|||
{"Three state beaver", ThreeStateBeaver}, |
|||
{"Five state beaver", FiveStateBeaver} |
|||
}; |
|||
var i: @indexof machines; |
|||
i := 0; |
|||
while i < @sizeof machines loop |
|||
print(machines[i].name); |
|||
print(": "); |
|||
var t := (machines[i].tf) (); |
|||
Run(t); |
|||
PrintTape(t, 32); |
|||
FreeTuring(t); |
|||
print_nl(); |
|||
i := i + 1; |
|||
end loop;</lang> |
|||
{{out}} |
|||
<pre>Simple incrementer: 1111 |
|||
Three state beaver: 111111 |
|||
Five state beaver: 10100100100100100100100100100100... (total length: 12289)</pre> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
===Nearly Strongly Typed Version=== |
===Nearly Strongly Typed Version=== |