all tasks
This commit is contained in:
parent
b83f433714
commit
68f8f3e56b
14735 changed files with 178959 additions and 0 deletions
35
Task/Universal-Turing-machine/0DESCRIPTION
Normal file
35
Task/Universal-Turing-machine/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
One of the foundational mathematical constructs behind computer science is the [[wp:Universal Turing machine|universal Turing Machine]]. Indeed one way to definitively prove that a language is Turing complete is to implement a universal Turing machine in it.
|
||||
|
||||
'''The task'''
|
||||
|
||||
For this task you would simulate such a machine capable of taking the definition of any other Turing machine and executing it. You will not, of course, have an infinite tape, but you should emulate this as much as is possible. The three permissible actions on the tape are "left", "right" and "stay".
|
||||
|
||||
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
|
||||
* '''Terminating states:''' qf
|
||||
* '''Permissible symbols:''' B, 1
|
||||
* '''Blank symbol:''' B
|
||||
* '''Rules:'''
|
||||
** (q0, 1, 1, right, q0)
|
||||
** (q0, B, 1, stay, qf)
|
||||
|
||||
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
|
||||
* '''Terminating states:''' halt
|
||||
* '''Permissible symbols:''' 0, 1
|
||||
* '''Blank symbol:''' 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)
|
||||
|
||||
The input for this machine should be an empty tape.
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
private with Ada.Containers.Doubly_Linked_Lists;
|
||||
|
||||
generic
|
||||
type State is (<>); -- State'First is starting state
|
||||
type Symbol is (<>); -- Symbol'First is blank
|
||||
package Turing is
|
||||
|
||||
Start: constant State := State'First;
|
||||
Halt: constant State := State'Last;
|
||||
subtype Action_State is State range Start .. State'Pred(Halt);
|
||||
|
||||
Blank: constant Symbol := Symbol'First;
|
||||
|
||||
type Movement is (Left, Stay, Right);
|
||||
|
||||
type Action is record
|
||||
New_State: State;
|
||||
Move_To: Movement;
|
||||
New_Symbol: Symbol;
|
||||
end record;
|
||||
|
||||
type Rules_Type is array(Action_State, Symbol) of Action;
|
||||
|
||||
type Tape_Type is limited private;
|
||||
|
||||
type Symbol_Map is array(Symbol) of Character;
|
||||
|
||||
function To_String(Tape: Tape_Type; Map: Symbol_Map) return String;
|
||||
function Position_To_String(Tape: Tape_Type; Marker: Character := '^')
|
||||
return String;
|
||||
function To_Tape(Str: String; Map: Symbol_Map) return Tape_Type;
|
||||
|
||||
procedure Single_Step(Current: in out State;
|
||||
Tape: in out Tape_Type;
|
||||
Rules: Rules_Type);
|
||||
|
||||
procedure Run(The_Tape: in out Tape_Type;
|
||||
Rules: Rules_Type;
|
||||
Max_Steps: Natural := Natural'Last;
|
||||
Print: access procedure(Tape: Tape_Type; Current: State));
|
||||
-- runs from Start State until either Halt or # Steps exceeds Max_Steps
|
||||
-- if # of steps exceeds Max_Steps, Constrained_Error is raised;
|
||||
-- if Print is not null, Print is called at the beginning of each step
|
||||
|
||||
private
|
||||
package Symbol_Lists is new Ada.Containers.Doubly_Linked_Lists(Symbol);
|
||||
subtype List is Symbol_Lists.List;
|
||||
|
||||
type Tape_Type is record
|
||||
Left: List;
|
||||
Here: Symbol;
|
||||
Right: List;
|
||||
end record;
|
||||
end Turing;
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package body Turing is
|
||||
|
||||
function List_To_String(L: List; Map: Symbol_Map) return String is
|
||||
LL: List := L;
|
||||
use type List;
|
||||
begin
|
||||
if L = Symbol_Lists.Empty_List then
|
||||
return "";
|
||||
else
|
||||
LL.Delete_First;
|
||||
return Map(L.First_Element) & List_To_String(LL, Map);
|
||||
end if;
|
||||
end List_To_String;
|
||||
|
||||
function To_String(Tape: Tape_Type; Map: Symbol_Map) return String is
|
||||
|
||||
begin
|
||||
return List_To_String(Tape.Left, Map) & Map(Tape.Here) &
|
||||
List_To_String(Tape.Right, Map);
|
||||
end To_String;
|
||||
|
||||
function Position_To_String(Tape: Tape_Type; Marker: Character := '^')
|
||||
return String is
|
||||
Blank_Map: Symbol_Map := (others => ' ');
|
||||
begin
|
||||
return List_To_String(Tape.Left, Blank_Map) & Marker &
|
||||
List_To_String(Tape.Right, Blank_Map);
|
||||
end Position_To_String;
|
||||
|
||||
function To_Tape(Str: String; Map: Symbol_Map) return Tape_Type is
|
||||
Char_Map: array(Character) of Symbol := (others => Blank);
|
||||
Tape: Tape_Type;
|
||||
begin
|
||||
if Str = "" then
|
||||
Tape.Here := Blank;
|
||||
else
|
||||
for S in Symbol loop
|
||||
Char_Map(Map(S)) := S;
|
||||
end loop;
|
||||
Tape.Here := Char_Map(Str(Str'First));
|
||||
for I in Str'First+1 .. Str'Last loop
|
||||
Tape.Right.Append(Char_Map(Str(I)));
|
||||
end loop;
|
||||
end if;
|
||||
return Tape;
|
||||
end To_Tape;
|
||||
|
||||
procedure Single_Step(Current: in out State;
|
||||
Tape: in out Tape_Type;
|
||||
Rules: Rules_Type) is
|
||||
Act: Action := Rules(Current, Tape.Here);
|
||||
use type List; -- needed to compare Tape.Left/Right to the Empty_List
|
||||
begin
|
||||
Current := Act.New_State; -- 1. update State
|
||||
Tape.Here := Act.New_Symbol; -- 2. write Symbol to Tape
|
||||
case Act.Move_To is -- 3. move Tape to the Left/Right or Stay
|
||||
when Left =>
|
||||
Tape.Right.Prepend(Tape.Here);
|
||||
if Tape.Left /= Symbol_Lists.Empty_List then
|
||||
Tape.Here := Tape.Left.Last_Element;
|
||||
Tape.Left.Delete_Last;
|
||||
else
|
||||
Tape.Here := Blank;
|
||||
end if;
|
||||
when Stay =>
|
||||
null; -- Stay where you are!
|
||||
when Right =>
|
||||
Tape.Left.Append(Tape.Here);
|
||||
if Tape.Right /= Symbol_Lists.Empty_List then
|
||||
Tape.Here := Tape.Right.First_Element;
|
||||
Tape.Right.Delete_First;
|
||||
else
|
||||
Tape.Here := Blank;
|
||||
end if;
|
||||
end case;
|
||||
end Single_Step;
|
||||
|
||||
procedure Run(The_Tape: in out Tape_Type;
|
||||
Rules: Rules_Type;
|
||||
Max_Steps: Natural := Natural'Last;
|
||||
Print: access procedure (Tape: Tape_Type; Current: State)) is
|
||||
The_State: State := Start;
|
||||
Steps: Natural := 0;
|
||||
begin
|
||||
Steps := 0;
|
||||
while (Steps <= Max_Steps) and (The_State /= Halt) loop
|
||||
if Print /= null then
|
||||
Print(The_Tape, The_State);
|
||||
end if;
|
||||
Steps := Steps + 1;
|
||||
Single_Step(The_State, The_Tape, Rules);
|
||||
end loop;
|
||||
if The_State /= Halt then
|
||||
raise Constraint_Error;
|
||||
end if;
|
||||
end Run;
|
||||
|
||||
end Turing;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
with Ada.Text_IO, Turing;
|
||||
|
||||
procedure Simple_Incrementer is
|
||||
|
||||
type States is (Start, Stop);
|
||||
type Symbols is (Blank, One);
|
||||
|
||||
package UTM is new Turing(States, Symbols);
|
||||
use UTM;
|
||||
|
||||
Map: Symbol_Map := (One => '1', Blank => '_');
|
||||
|
||||
Rules: Rules_Type :=
|
||||
(Start => (One => (Start, Right, One),
|
||||
Blank => (Stop, Stay, One)));
|
||||
Tape: Tape_Type := To_Tape("111", Map);
|
||||
|
||||
procedure Put_Tape(Tape: Tape_Type; Current: States) is
|
||||
begin
|
||||
Ada.Text_IO.Put_Line(To_String(Tape, Map) & " " & States'Image(Current));
|
||||
Ada.Text_IO.Put_Line(Position_To_String(Tape));
|
||||
end Put_Tape;
|
||||
|
||||
begin
|
||||
Run(Tape, Rules, 20, null); -- don't print the configuration during running
|
||||
Put_Tape(Tape, Stop); -- print the final configuration
|
||||
end Simple_Incrementer;
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
with Ada.Text_IO, Turing;
|
||||
|
||||
procedure Busy_Beaver_3 is
|
||||
|
||||
type States is (A, B, C, Stop);
|
||||
type Symbols is range 0 .. 1;
|
||||
package UTM is new Turing(States, Symbols); use UTM;
|
||||
|
||||
Map: Symbol_Map := (1 => '1', 0 => '0');
|
||||
|
||||
Rules: Rules_Type :=
|
||||
(A => (0 => (New_State => B, Move_To => Right, New_Symbol => 1),
|
||||
1 => (New_State => C, Move_To => Left, New_Symbol => 1)),
|
||||
B => (0 => (New_State => A, Move_To => Left, New_Symbol => 1),
|
||||
1 => (New_State => B, Move_To => Right, New_Symbol => 1)),
|
||||
C => (0 => (New_State => B, Move_To => Left, New_Symbol => 1),
|
||||
1 => (New_State => Stop, Move_To => Stay, New_Symbol => 1)));
|
||||
|
||||
Tape: Tape_Type := To_Tape("", Map);
|
||||
|
||||
procedure Put_Tape(Tape: Tape_Type; Current: States) is
|
||||
begin
|
||||
Ada.Text_IO.Put_Line(To_String(Tape, Map) & " " &
|
||||
States'Image(Current));
|
||||
Ada.Text_IO.Put_Line(Position_To_String(Tape));
|
||||
end Put_Tape;
|
||||
|
||||
begin
|
||||
Run(Tape, Rules, 20, Put_Tape'Access); -- print configuration before each step
|
||||
Put_Tape(Tape, Stop); -- and print the final configuration
|
||||
end Busy_Beaver_3;
|
||||
190
Task/Universal-Turing-machine/D/universal-turing-machine.d
Normal file
190
Task/Universal-Turing-machine/D/universal-turing-machine.d
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
import std.stdio, std.algorithm, std.string, std.conv, std.array,
|
||||
std.exception;
|
||||
|
||||
struct UTM(bool doShow=true) {
|
||||
alias Symbol = uint;
|
||||
alias State = char; // Typedef?
|
||||
enum Direction { right, left, stay }
|
||||
|
||||
private TapeHead head;
|
||||
private const TuringMachine tm;
|
||||
|
||||
static struct Rule {
|
||||
Symbol toWrite;
|
||||
Direction direction;
|
||||
State nextState;
|
||||
}
|
||||
|
||||
static struct TuringMachine {
|
||||
Symbol[] symbols;
|
||||
Symbol blank;
|
||||
State initialState;
|
||||
State[] haltStates, runningStates;
|
||||
Rule[Symbol][State] rules;
|
||||
Symbol[] input;
|
||||
}
|
||||
|
||||
static struct TapeHead {
|
||||
immutable Symbol blank;
|
||||
Symbol[] tape;
|
||||
size_t position;
|
||||
|
||||
this(in ref TuringMachine t) pure /*nothrow*/ {
|
||||
this.blank = t.blank;
|
||||
this.tape = t.input.dup; // Not nothrow.
|
||||
if (this.tape.empty)
|
||||
this.tape = [this.blank];
|
||||
this.position = 0;
|
||||
}
|
||||
|
||||
pure nothrow invariant() {
|
||||
assert(this.position < this.tape.length);
|
||||
}
|
||||
|
||||
Symbol read() const pure nothrow {
|
||||
return this.tape[this.position];
|
||||
}
|
||||
|
||||
void show() const {
|
||||
.write(this);
|
||||
}
|
||||
|
||||
void write(in Symbol symbol) {
|
||||
static if (doShow)
|
||||
show();
|
||||
this.tape[this.position] = symbol;
|
||||
}
|
||||
|
||||
void right() pure nothrow {
|
||||
this.position++;
|
||||
if (this.position == this.tape.length)
|
||||
this.tape ~= this.blank;
|
||||
}
|
||||
|
||||
void left() pure nothrow {
|
||||
if (this.position == 0)
|
||||
this.tape = this.blank ~ this.tape;
|
||||
else
|
||||
this.position--;
|
||||
}
|
||||
|
||||
void move(in Direction dir) {
|
||||
final switch (dir) {
|
||||
case Direction.left: left(); break;
|
||||
case Direction.right: right(); break;
|
||||
case Direction.stay: /*Do nothing.*/ break;
|
||||
}
|
||||
}
|
||||
|
||||
string toString() const {
|
||||
return format("...%(%)...", this.tape)
|
||||
~ '\n'
|
||||
~ format("%" ~ text(this.position + 4) ~ "s", "^")
|
||||
~ '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void show() const {
|
||||
head.show();
|
||||
}
|
||||
|
||||
this(const ref TuringMachine tm_) {
|
||||
immutable errMsg = "Invalid input.";
|
||||
enforce(!tm_.runningStates.empty, errMsg);
|
||||
enforce(!tm_.haltStates.empty, errMsg);
|
||||
enforce(!tm_.symbols.empty, errMsg);
|
||||
enforce(tm_.rules.length, errMsg);
|
||||
enforce(tm_.runningStates.canFind(tm_.initialState), errMsg);
|
||||
enforce(tm_.symbols.canFind(tm_.blank), errMsg);
|
||||
const allStates = tm_.runningStates ~ tm_.haltStates;
|
||||
foreach (const s; tm_.rules.keys.to!(dchar[])().sort())
|
||||
enforce(tm_.runningStates.canFind(s), errMsg);
|
||||
foreach (const aa; tm_.rules.byValue)
|
||||
foreach (/*const*/ s, const rule; aa) {
|
||||
enforce(tm_.symbols.canFind(s), errMsg);
|
||||
enforce(tm_.symbols.canFind(rule.toWrite), errMsg);
|
||||
enforce(allStates.canFind(rule.nextState), errMsg);
|
||||
}
|
||||
|
||||
this.tm = tm_;
|
||||
this.head = TapeHead(this.tm);
|
||||
|
||||
State state = this.tm.initialState;
|
||||
while (true) {
|
||||
if (tm.haltStates.canFind(state))
|
||||
break;
|
||||
if (!tm.runningStates.canFind(state))
|
||||
throw new Exception("Unknown state.");
|
||||
immutable symbol = this.head.read();
|
||||
immutable rule = this.tm.rules[state][symbol];
|
||||
this.head.write(rule.toWrite);
|
||||
this.head.move(rule.direction);
|
||||
state = rule.nextState;
|
||||
}
|
||||
static if (doShow)
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
with (UTM!()) {
|
||||
alias R = Rule;
|
||||
writeln("Incrementer:");
|
||||
TuringMachine tm1;
|
||||
tm1.symbols = [0, 1];
|
||||
tm1.blank = 0;
|
||||
tm1.initialState = 'A';
|
||||
tm1.haltStates = ['H'];
|
||||
tm1.runningStates = ['A'];
|
||||
with (Direction)
|
||||
tm1.rules = ['A': [0: R(1, left, 'H'),
|
||||
1: R(1, right, 'A')]];
|
||||
tm1.input = [1, 1, 1];
|
||||
UTM!()(tm1);
|
||||
|
||||
// http://en.wikipedia.org/wiki/Busy_beaver
|
||||
writeln("\nBusy beaver machine (3-state, 2-symbol):");
|
||||
TuringMachine tm2;
|
||||
tm2.symbols = [0, 1];
|
||||
tm2.blank = 0;
|
||||
tm2.initialState = 'A';
|
||||
tm2.haltStates = ['H'];
|
||||
tm2.runningStates = ['A', 'B', 'C'];
|
||||
with (Direction)
|
||||
tm2.rules = ['A': [0: R(1, right, 'B'),
|
||||
1: R(1, left, 'C')],
|
||||
'B': [0: R(1, left, 'A'),
|
||||
1: R(1, right, 'B')],
|
||||
'C': [0: R(1, left, 'B'),
|
||||
1: R(1, stay, 'H')]];
|
||||
UTM!()(tm2);
|
||||
}
|
||||
|
||||
with (UTM!false) {
|
||||
writeln("\nSorting stress test (12212212121212):");
|
||||
alias R = Rule;
|
||||
TuringMachine tm3;
|
||||
tm3.symbols = [0, 1, 2, 3];
|
||||
tm3.blank = 0;
|
||||
tm3.initialState = 'A';
|
||||
tm3.haltStates = ['H'];
|
||||
tm3.runningStates = ['A', 'B', 'C', 'D', 'E'];
|
||||
with (Direction)
|
||||
tm3.rules = ['A': [1: R(1, right, 'A'),
|
||||
2: R(3, right, 'B'),
|
||||
0: R(0, left, 'E')],
|
||||
'B': [1: R(1, right, 'B'),
|
||||
2: R(2, right, 'B'),
|
||||
0: R(0, left, 'C')],
|
||||
'C': [1: R(2, left, 'D'),
|
||||
2: R(2, left, 'C'),
|
||||
3: R(2, left, 'E')],
|
||||
'D': [1: R(1, left, 'D'),
|
||||
2: R(2, left, 'D'),
|
||||
3: R(1, right, 'A')],
|
||||
'E': [1: R(1, left, 'E'),
|
||||
0: R(0, right, 'H')]];
|
||||
tm3.input = [1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2];
|
||||
UTM!false(tm3).show();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/env escript
|
||||
|
||||
-module(turing).
|
||||
-mode(compile).
|
||||
|
||||
-export([main/1]).
|
||||
|
||||
% Incrementer definition:
|
||||
% States: a | halt
|
||||
% Initial state: a
|
||||
% Halting states: halt
|
||||
% Symbols: b | '1'
|
||||
% Blank symbol: b
|
||||
incrementer_config() -> {a, [halt], b}.
|
||||
incrementer(a, '1') -> {'1', right, a};
|
||||
incrementer(a, b) -> {'1', stay, halt}.
|
||||
|
||||
% Busy beaver definition:
|
||||
% States: a | b | c | halt
|
||||
% Initial state: a
|
||||
% Halting states: halt
|
||||
% Symbols: '0' | '1'
|
||||
% Blank symbol: '0'
|
||||
busy_beaver_config() -> {a, [halt], '0'}.
|
||||
busy_beaver(a, '0') -> {'1', right, b};
|
||||
busy_beaver(a, '1') -> {'1', left, c};
|
||||
busy_beaver(b, '0') -> {'1', left, a};
|
||||
busy_beaver(b, '1') -> {'1', right, b};
|
||||
busy_beaver(c, '0') -> {'1', left, b};
|
||||
busy_beaver(c, '1') -> {'1', stay, halt}.
|
||||
|
||||
% Mainline code.
|
||||
main([]) ->
|
||||
io:format("==============================~n"),
|
||||
io:format("Turing machine simulator test.~n"),
|
||||
io:format("==============================~n"),
|
||||
|
||||
Tape1 = turing(fun incrementer_config/0, fun incrementer/2, ['1','1','1']),
|
||||
io:format("~w~n", [Tape1]),
|
||||
|
||||
Tape2 = turing(fun busy_beaver_config/0, fun busy_beaver/2, []),
|
||||
io:format("~w~n", [Tape2]).
|
||||
|
||||
% Universal Turing machine simulator.
|
||||
turing(Config, Rules, Input) ->
|
||||
{Start, _, _} = Config(),
|
||||
{Left, Right} = perform(Config, Rules, Start, {[], Input}),
|
||||
lists:reverse(Left) ++ Right.
|
||||
|
||||
perform(Config, Rules, State, Input = {LeftInput, RightInput}) ->
|
||||
{_, Halts, Blank} = Config(),
|
||||
case lists:member(State, Halts) of
|
||||
true -> Input;
|
||||
false ->
|
||||
{NewRight, Symbol} = symbol(RightInput, Blank),
|
||||
{NewSymbol, Action, NewState} = Rules(State, Symbol),
|
||||
NewInput = action(Action, Blank, {LeftInput, [NewSymbol| NewRight]}),
|
||||
perform(Config, Rules, NewState, NewInput)
|
||||
end.
|
||||
|
||||
symbol([], Blank) -> {[], Blank};
|
||||
symbol([S|R], _) -> {R, S}.
|
||||
|
||||
action(left, Blank, {[], Right}) -> {[], [Blank|Right]};
|
||||
action(left, _, {[L|Ls], Right}) -> {Ls, [L|Right]};
|
||||
action(stay, _, Tape) -> Tape;
|
||||
action(right, Blank, {Left, []}) -> {[Blank|Left], []};
|
||||
action(right, _, {Left, [R|Rs]}) -> {[R|Left], Rs}.
|
||||
238
Task/Universal-Turing-machine/Java/universal-turing-machine.java
Normal file
238
Task/Universal-Turing-machine/Java/universal-turing-machine.java
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.ListIterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
|
||||
public class UTM {
|
||||
private List<String> tape;
|
||||
private String blankSymbol;
|
||||
private ListIterator<String> head;
|
||||
private Map<StateTapeSymbolPair, Transition> transitions = new HashMap<StateTapeSymbolPair, Transition>();
|
||||
private Set<String> terminalStates;
|
||||
private String initialState;
|
||||
|
||||
public UTM(Set<Transition> transitions, Set<String> terminalStates, String initialState, String blankSymbol) {
|
||||
this.blankSymbol = blankSymbol;
|
||||
for (Transition t : transitions) {
|
||||
this.transitions.put(t.from, t);
|
||||
}
|
||||
this.terminalStates = terminalStates;
|
||||
this.initialState = initialState;
|
||||
}
|
||||
|
||||
public static class StateTapeSymbolPair {
|
||||
private String state;
|
||||
private String tapeSymbol;
|
||||
|
||||
public StateTapeSymbolPair(String state, String tapeSymbol) {
|
||||
this.state = state;
|
||||
this.tapeSymbol = tapeSymbol;
|
||||
}
|
||||
|
||||
// These methods can be auto-generated by Eclipse.
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((state == null) ? 0 : state.hashCode());
|
||||
result = prime
|
||||
* result
|
||||
+ ((tapeSymbol == null) ? 0 : tapeSymbol
|
||||
.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
// These methods can be auto-generated by Eclipse.
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
StateTapeSymbolPair other = (StateTapeSymbolPair) obj;
|
||||
if (state == null) {
|
||||
if (other.state != null)
|
||||
return false;
|
||||
} else if (!state.equals(other.state))
|
||||
return false;
|
||||
if (tapeSymbol == null) {
|
||||
if (other.tapeSymbol != null)
|
||||
return false;
|
||||
} else if (!tapeSymbol.equals(other.tapeSymbol))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + state + "," + tapeSymbol + ")";
|
||||
}
|
||||
}
|
||||
|
||||
public static class Transition {
|
||||
private StateTapeSymbolPair from;
|
||||
private StateTapeSymbolPair to;
|
||||
private int direction; // -1 left, 0 neutral, 1 right.
|
||||
|
||||
public Transition(StateTapeSymbolPair from, StateTapeSymbolPair to, int direction) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return from + "=>" + to + "/" + direction;
|
||||
}
|
||||
}
|
||||
|
||||
public void initializeTape(List<String> input) { // Arbitrary Strings as symbols.
|
||||
tape = input;
|
||||
}
|
||||
|
||||
public void initializeTape(String input) { // Uses single characters as symbols.
|
||||
tape = new LinkedList<String>();
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
tape.add(input.charAt(i) + "");
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> runTM() { // Returns null if not in terminal state.
|
||||
if (tape.size() == 0) {
|
||||
tape.add(blankSymbol);
|
||||
}
|
||||
|
||||
head = tape.listIterator();
|
||||
head.next();
|
||||
head.previous();
|
||||
|
||||
StateTapeSymbolPair tsp = new StateTapeSymbolPair(initialState, tape.get(0));
|
||||
|
||||
while (transitions.containsKey(tsp)) { // While a matching transition exists.
|
||||
System.out.println(this + " --- " + transitions.get(tsp));
|
||||
Transition trans = transitions.get(tsp);
|
||||
head.set(trans.to.tapeSymbol); // Write tape symbol.
|
||||
tsp.state = trans.to.state; // Change state.
|
||||
if (trans.direction == -1) { // Go left.
|
||||
if (!head.hasPrevious()) {
|
||||
head.add(blankSymbol); // Extend tape.
|
||||
}
|
||||
tsp.tapeSymbol = head.previous(); // Memorize tape symbol.
|
||||
} else if (trans.direction == 1) { // Go right.
|
||||
head.next();
|
||||
if (!head.hasNext()) {
|
||||
head.add(blankSymbol); // Extend tape.
|
||||
head.previous();
|
||||
}
|
||||
tsp.tapeSymbol = head.next(); // Memorize tape symbol.
|
||||
head.previous();
|
||||
} else {
|
||||
tsp.tapeSymbol = trans.to.tapeSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(this + " --- " + tsp);
|
||||
|
||||
if (terminalStates.contains(tsp.state)) {
|
||||
return tape;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
int headPos = head.previousIndex();
|
||||
String s = "[ ";
|
||||
|
||||
for (int i = 0; i <= headPos; i++) {
|
||||
s += tape.get(i) + " ";
|
||||
}
|
||||
|
||||
s += "[H] ";
|
||||
|
||||
for (int i = headPos + 1; i < tape.size(); i++) {
|
||||
s += tape.get(i) + " ";
|
||||
}
|
||||
|
||||
return s + "]";
|
||||
} catch (Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Simple incrementer.
|
||||
String init = "q0";
|
||||
String blank = "b";
|
||||
|
||||
Set<String> term = new HashSet<String>();
|
||||
term.add("qf");
|
||||
|
||||
Set<Transition> trans = new HashSet<Transition>();
|
||||
|
||||
trans.add(new Transition(new StateTapeSymbolPair("q0", "1"), new StateTapeSymbolPair("q0", "1"), 1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("q0", "b"), new StateTapeSymbolPair("qf", "1"), 0));
|
||||
|
||||
UTM machine = new UTM(trans, term, init, blank);
|
||||
machine.initializeTape("111");
|
||||
System.out.println("Output (si): " + machine.runTM() + "\n");
|
||||
|
||||
// Busy Beaver (overwrite variables from above).
|
||||
init = "a";
|
||||
|
||||
term.clear();
|
||||
term.add("halt");
|
||||
|
||||
blank = "0";
|
||||
|
||||
trans.clear();
|
||||
|
||||
// Change state from "a" to "b" if "0" is read on tape, write "1" and go to the right. (-1 left, 0 nothing, 1 right.)
|
||||
trans.add(new Transition(new StateTapeSymbolPair("a", "0"), new StateTapeSymbolPair("b", "1"), 1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("a", "1"), new StateTapeSymbolPair("c", "1"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("b", "0"), new StateTapeSymbolPair("a", "1"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("b", "1"), new StateTapeSymbolPair("b", "1"), 1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("c", "0"), new StateTapeSymbolPair("b", "1"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("c", "1"), new StateTapeSymbolPair("halt", "1"), 0));
|
||||
|
||||
machine = new UTM(trans, term, init, blank);
|
||||
machine.initializeTape("");
|
||||
System.out.println("Output (bb): " + machine.runTM());
|
||||
|
||||
// Sorting test (overwrite variables from above).
|
||||
init = "s0";
|
||||
blank = "*";
|
||||
|
||||
term = new HashSet<String>();
|
||||
term.add("see");
|
||||
|
||||
trans = new HashSet<Transition>();
|
||||
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s0", "a"), new StateTapeSymbolPair("s0", "a"), 1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s0", "b"), new StateTapeSymbolPair("s1", "B"), 1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s0", "*"), new StateTapeSymbolPair("se", "*"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s1", "a"), new StateTapeSymbolPair("s1", "a"), 1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s1", "b"), new StateTapeSymbolPair("s1", "b"), 1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s1", "*"), new StateTapeSymbolPair("s2", "*"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s2", "a"), new StateTapeSymbolPair("s3", "b"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s2", "b"), new StateTapeSymbolPair("s2", "b"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s2", "B"), new StateTapeSymbolPair("se", "b"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s3", "a"), new StateTapeSymbolPair("s3", "a"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s3", "b"), new StateTapeSymbolPair("s3", "b"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("s3", "B"), new StateTapeSymbolPair("s0", "a"), 1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("se", "a"), new StateTapeSymbolPair("se", "a"), -1));
|
||||
trans.add(new Transition(new StateTapeSymbolPair("se", "*"), new StateTapeSymbolPair("see", "*"), 1));
|
||||
|
||||
machine = new UTM(trans, term, init, blank);
|
||||
machine.initializeTape("babbababaa");
|
||||
System.out.println("Output (sort): " + machine.runTM() + "\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
:- module turing.
|
||||
|
||||
:- interface.
|
||||
|
||||
:- import_module list.
|
||||
:- import_module set.
|
||||
|
||||
:- type config(State, Symbol)
|
||||
---> config(initial_state :: State,
|
||||
halting_states :: set(State),
|
||||
blank :: Symbol ).
|
||||
|
||||
:- type action ---> left ; stay ; right.
|
||||
|
||||
:- func turing(config(State, Symbol),
|
||||
pred(State, Symbol, Symbol, action, State),
|
||||
list(Symbol)) = list(Symbol).
|
||||
:- mode turing(in,
|
||||
pred(in, in, out, out, out) is semidet,
|
||||
in) = out is det.
|
||||
|
||||
:- implementation.
|
||||
|
||||
:- import_module pair.
|
||||
:- import_module require.
|
||||
|
||||
turing(Config@config(Start, _, _), Rules, Input) = Output :-
|
||||
(Left-Right) = perform(Config, Rules, Start, ([]-Input)),
|
||||
Output = append(reverse(Left), Right).
|
||||
|
||||
:- func perform(config(State, Symbol),
|
||||
pred(State, Symbol, Symbol, action, State),
|
||||
State, pair(list(Symbol))) = pair(list(Symbol)).
|
||||
:- mode perform(in, pred(in, in, out, out, out) is semidet,
|
||||
in, in) = out is det.
|
||||
perform(Config@config(_, Halts, Blank), Rules, State,
|
||||
Input@(LeftInput-RightInput)) = Output :-
|
||||
symbol(RightInput, Blank, RightNew, Symbol),
|
||||
( set.member(State, Halts) ->
|
||||
Output = Input
|
||||
; Rules(State, Symbol, NewSymbol, Action, NewState) ->
|
||||
NewLeft = pair(LeftInput, [NewSymbol|RightNew]),
|
||||
NewRight = action(Action, Blank, NewLeft),
|
||||
Output = perform(Config, Rules, NewState, NewRight)
|
||||
;
|
||||
error("an impossible state has apparently become possible") ).
|
||||
|
||||
:- pred symbol(list(Symbol), Symbol, list(Symbol), Symbol).
|
||||
:- mode symbol(in, in, out, out) is det.
|
||||
symbol([], Blank, [], Blank).
|
||||
symbol([Sym|Rem], _, Rem, Sym).
|
||||
|
||||
:- func action(action, State, pair(list(State))) = pair(list(State)).
|
||||
action(left, Blank, ([]-Right)) = ([]-[Blank|Right]).
|
||||
action(left, _, ([Left|Lefts]-Rights)) = (Lefts-[Left|Rights]).
|
||||
action(stay, _, Tape) = Tape.
|
||||
action(right, Blank, (Left-[])) = ([Blank|Left]-[]).
|
||||
action(right, _, (Left-[Right|Rights])) = ([Right|Left]-Rights).
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
:- type incrementer_states ---> a ; halt.
|
||||
:- type incrementer_symbols ---> b ; '1'.
|
||||
|
||||
:- func incrementer_config = config(incrementer_states, incrementer_symbols).
|
||||
incrementer_config = config(a, % the initial state
|
||||
set([halt]), % the set of halting states
|
||||
b). % the blank symbol
|
||||
|
||||
:- pred incrementer(incrementer_states::in,
|
||||
incrementer_symbols::in,
|
||||
incrementer_symbols::out,
|
||||
action::out,
|
||||
incrementer_states::out) is semidet.
|
||||
incrementer(a, '1', '1', right, a).
|
||||
incrementer(a, b, '1', stay, halt).
|
||||
|
||||
TapeOut = turing(incrementer_config, incrementer, [1, 1, 1]).
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
:- type busy_beaver_states ---> a ; b ; c ; halt.
|
||||
:- type busy_beaver_symbols ---> '0' ; '1'.
|
||||
|
||||
:- func busy_beaver_config = config(busy_beaver_states, busy_beaver_symbols).
|
||||
busy_beaver_config = config(a, % initial state
|
||||
set([halt]), % set of terminating states
|
||||
'0'). % blank symbol
|
||||
|
||||
:- pred busy_beaver(busy_beaver_states::in,
|
||||
busy_beaver_symbols::in,
|
||||
busy_beaver_symbols::out,
|
||||
action::out,
|
||||
busy_beaver_states::out) is semidet.
|
||||
busy_beaver(a, '0', '1', right, b).
|
||||
busy_beaver(a, '1', '1', left, c).
|
||||
busy_beaver(b, '0', '1', left, a).
|
||||
busy_beaver(b, '1', '1', right, b).
|
||||
busy_beaver(c, '0', '1', left, b).
|
||||
busy_beaver(c, '1', '1', stay, halt).
|
||||
|
||||
TapeOut = turing(busy_beaver_config, busy_beaver, []).
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
sub run_utm(:$state! is copy, :$blank!, :@rules!, :@tape = [$blank], :$halt, :$pos is copy = 0) {
|
||||
$pos += @tape if $pos < 0;
|
||||
die "Bad initial position" unless $pos ~~ ^@tape;
|
||||
|
||||
step:
|
||||
print "$state\t";
|
||||
for ^@tape {
|
||||
my $v = @tape[$_];
|
||||
print $_ == $pos ?? "[$v]" !! " $v ";
|
||||
}
|
||||
print "\n";
|
||||
|
||||
return if $state eq $halt;
|
||||
for @rules -> @rule {
|
||||
my ($s0, $v0, $v1, $dir, $s1) = @rule;
|
||||
next unless $s0 eq $state and @tape[$pos] eq $v0;
|
||||
|
||||
@tape[$pos] = $v1;
|
||||
|
||||
given $dir {
|
||||
when 'left' {
|
||||
if $pos == 0 { unshift @tape, $blank }
|
||||
else { $pos-- }
|
||||
}
|
||||
when 'right' {
|
||||
push @tape, $blank if ++$pos >= @tape;
|
||||
}
|
||||
}
|
||||
|
||||
$state = $s1;
|
||||
goto step;
|
||||
}
|
||||
|
||||
die "No matching rules";
|
||||
}
|
||||
|
||||
say "incr machine";
|
||||
run_utm :halt<qf>,
|
||||
:state<q0>,
|
||||
:tape[1,1,1],
|
||||
:blank<B>,
|
||||
:rules[ [< q0 1 1 right q0 >],]
|
||||
[< q0 B 1 stay qf >] ];
|
||||
|
||||
say "\nbusy beaver";
|
||||
run_utm :halt<halt>,
|
||||
:state<a>,
|
||||
: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 >] ];
|
||||
|
||||
say "\nsorting test";
|
||||
run_utm :halt<STOP>,
|
||||
:state<A>,
|
||||
:blank<0>,
|
||||
:tape[< 2 2 2 1 2 2 1 2 1 2 1 2 1 2 >],
|
||||
:rules[ [< A 1 1 right A >],]
|
||||
[< A 2 3 right B >],
|
||||
[< A 0 0 left E >],
|
||||
[< B 1 1 right B >],
|
||||
[< B 2 2 right B >],
|
||||
[< B 0 0 left C >],
|
||||
[< C 1 2 left D >],
|
||||
[< C 2 2 left C >],
|
||||
[< C 3 2 left E >],
|
||||
[< D 1 1 left D >],
|
||||
[< D 2 2 left D >],
|
||||
[< D 3 1 right A >],
|
||||
[< E 1 1 left E >],
|
||||
[< E 0 0 right STOP >] ];
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub run_utm {
|
||||
my %o = @_;
|
||||
my $st = $o{state} // die "init head state undefined";
|
||||
my $blank = $o{blank} // die "blank symbol undefined";
|
||||
my @rules = @{$o{rules}} or die "rules undefined";
|
||||
my @tape = $o{tape} ? @{$o{tape}} : ($blank);
|
||||
my $halt = $o{halt};
|
||||
|
||||
my $pos = $o{pos} // 0;
|
||||
$pos += @tape if $pos < 0;
|
||||
die "bad init position" if $pos >= @tape || $pos < 0;
|
||||
|
||||
step: while (1) {
|
||||
print "$st\t";
|
||||
for (0 .. $#tape) {
|
||||
my $v = $tape[$_];
|
||||
print $_ == $pos ? "[$v]" : " $v ";
|
||||
}
|
||||
print "\n";
|
||||
|
||||
last if $st eq $halt;
|
||||
for (@rules) {
|
||||
my ($s0, $v0, $v1, $dir, $s1) = @$_;
|
||||
next unless $s0 eq $st and $tape[$pos] eq $v0;
|
||||
|
||||
$tape[$pos] = $v1;
|
||||
|
||||
if ($dir eq 'left') {
|
||||
if ($pos == 0) { unshift @tape, $blank}
|
||||
else { $pos-- }
|
||||
} elsif ($dir eq 'right') {
|
||||
push @tape, $blank if ++$pos >= @tape
|
||||
}
|
||||
|
||||
$st = $s1;
|
||||
next step;
|
||||
}
|
||||
|
||||
die "no matching rules";
|
||||
}
|
||||
}
|
||||
|
||||
print "incr machine\n";
|
||||
run_utm halt=>'qf',
|
||||
state=>'q0',
|
||||
tape=>[1,1,1],
|
||||
blank=>'B',
|
||||
rules=>[[qw/q0 1 1 right q0/],
|
||||
[qw/q0 B 1 stay qf/]];
|
||||
|
||||
print "\nbusy beaver\n";
|
||||
run_utm halt=>'halt',
|
||||
state=>'a',
|
||||
blank=>'0',
|
||||
rules=>[[qw/a 0 1 right b/],
|
||||
[qw/a 1 1 left c/],
|
||||
[qw/b 0 1 left a/],
|
||||
[qw/b 1 1 right b/],
|
||||
[qw/c 0 1 left b/],
|
||||
[qw/c 1 1 stay halt/]];
|
||||
|
||||
print "\nsorting test\n";
|
||||
run_utm halt=>'STOP',
|
||||
state=>'A',
|
||||
blank=>'0',
|
||||
tape=>[qw/2 2 2 1 2 2 1 2 1 2 1 2 1 2/],
|
||||
rules=>[[qw/A 1 1 right A/],
|
||||
[qw/A 2 3 right B/],
|
||||
[qw/A 0 0 left E/],
|
||||
[qw/B 1 1 right B/],
|
||||
[qw/B 2 2 right B/],
|
||||
[qw/B 0 0 left C/],
|
||||
[qw/C 1 2 left D/],
|
||||
[qw/C 2 2 left C/],
|
||||
[qw/C 3 2 left E/],
|
||||
[qw/D 1 1 left D/],
|
||||
[qw/D 2 2 left D/],
|
||||
[qw/D 3 1 right A/],
|
||||
[qw/E 1 1 left E/],
|
||||
[qw/E 0 0 right STOP/]];
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
turing(Config, Rules, TapeIn, TapeOut) :-
|
||||
call(Config, IS, _, _, _, _),
|
||||
perform(Config, Rules, IS, {[], TapeIn}, {Ls, Rs}),
|
||||
reverse(Ls, Ls1),
|
||||
append(Ls1, Rs, TapeOut).
|
||||
|
||||
perform(Config, Rules, State, TapeIn, TapeOut) :-
|
||||
call(Config, _, FS, RS, B, Symbols),
|
||||
( memberchk(State, FS) ->
|
||||
TapeOut = TapeIn
|
||||
; memberchk(State, RS) ->
|
||||
{LeftIn, RightIn} = TapeIn,
|
||||
symbol(RightIn, Symbol, RightRem, B),
|
||||
memberchk(Symbol, Symbols),
|
||||
once(call(Rules, State, Symbol, NewSymbol, Action, NewState)),
|
||||
memberchk(NewSymbol, Symbols),
|
||||
action(Action, {LeftIn, [NewSymbol|RightRem]}, {LeftOut, RightOut}, B),
|
||||
perform(Config, Rules, NewState, {LeftOut, RightOut}, TapeOut) ).
|
||||
|
||||
symbol([], B, [], B).
|
||||
symbol([Sym|Rs], Sym, Rs, _).
|
||||
|
||||
action(left, {Lin, Rin}, {Lout, Rout}, B) :- left(Lin, Rin, Lout, Rout, B).
|
||||
action(stay, Tape, Tape, _).
|
||||
action(right, {Lin, Rin}, {Lout, Rout}, B) :- right(Lin, Rin, Lout, Rout, B).
|
||||
|
||||
left([], Rs, [], [B|Rs], B).
|
||||
left([L|Ls], Rs, Ls, [L|Rs], _).
|
||||
|
||||
right(L, [], [B|L], [], B).
|
||||
right(L, [S|Rs], [S|L], Rs, _).
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
incrementer_config(IS, FS, RS, B, S) :-
|
||||
IS = q0, % initial state
|
||||
FS = [qf], % halting states
|
||||
RS = [IS], % running states
|
||||
B = 0, % blank symbol
|
||||
S = [B, 1]. % valid symbols
|
||||
incrementer(q0, 1, 1, right, q0).
|
||||
incrementer(q0, b, 1, stay, qf).
|
||||
|
||||
turing(incrementer_config, incrementer, [1, 1, 1], TapeOut).
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
busy_beaver_config(IS, FS, RS, B, S) :-
|
||||
IS = 'A', % initial state
|
||||
FS = ['HALT'], % halting states
|
||||
RS = [IS, 'B', 'C'], % running states
|
||||
B = 0, % blank symbol
|
||||
S = [B, 1]. % valid symbols
|
||||
busy_beaver('A', 0, 1, right, 'B').
|
||||
busy_beaver('A', 1, 1, left, 'C').
|
||||
busy_beaver('B', 0, 1, left, 'A').
|
||||
busy_beaver('B', 1, 1, right, 'B').
|
||||
busy_beaver('C', 0, 1, left, 'B').
|
||||
busy_beaver('C', 1, 1, stay, 'HALT').
|
||||
|
||||
turing(busy_beaver_config, busy_beaver, [], TapeOut).
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
class Turing
|
||||
class Tape
|
||||
def initialize(symbols, blank, starting_tape)
|
||||
@symbols = symbols
|
||||
@blank = blank
|
||||
@tape = starting_tape
|
||||
@index = 0
|
||||
end
|
||||
def read
|
||||
retval = @tape[@index]
|
||||
unless retval
|
||||
retval = @tape[@index] = @blank
|
||||
end
|
||||
raise "invalid symbol '#{retval}' on tape" unless @tape.member?(retval)
|
||||
return retval
|
||||
end
|
||||
def write(symbol)
|
||||
@tape[@index] = symbol
|
||||
end
|
||||
def right
|
||||
@index += 1
|
||||
end
|
||||
def left
|
||||
if @index == 0
|
||||
@tape.unshift @blank
|
||||
else
|
||||
@index -= 1
|
||||
end
|
||||
end
|
||||
def stay
|
||||
# nop
|
||||
end
|
||||
def get_tape
|
||||
return @tape
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(symbols, blank,
|
||||
initial_state, halt_states, running_states,
|
||||
rules, starting_tape = [])
|
||||
@tape = Tape.new(symbols, blank, starting_tape)
|
||||
@initial_state = initial_state
|
||||
@halt_states = halt_states
|
||||
@running_states = running_states
|
||||
@rules = rules
|
||||
@halted = false
|
||||
end
|
||||
def run
|
||||
raise "machine already halted" if @halted
|
||||
state = @initial_state
|
||||
while (true)
|
||||
break if @halt_states.member? state
|
||||
raise "unknown state '#{state}'" unless @running_states.member? state
|
||||
symbol = @tape.read
|
||||
outsym, action, state = @rules[state][symbol]
|
||||
@tape.write outsym
|
||||
@tape.send action
|
||||
end
|
||||
@halted = true
|
||||
return @tape.get_tape
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
incrementer_rules = {
|
||||
:q0 => { 1 => [1, :right, :q0],
|
||||
:b => [1, :stay, :qf]}
|
||||
}
|
||||
t = Turing.new([:b, 1], # permitted symbols
|
||||
:b, # blank symbol
|
||||
:q0, # starting state
|
||||
[:qf], # terminating states
|
||||
[:q0], # running states
|
||||
incrementer_rules, # operating rules
|
||||
[1, 1, 1]) # starting tape
|
||||
print t.run, "\n"
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
busy_beaver_rules = {
|
||||
:a => { 0 => [1, :right, :b],
|
||||
1 => [1, :left, :c]},
|
||||
:b => { 0 => [1, :left, :a],
|
||||
1 => [1, :right, :b]},
|
||||
:c => { 0 => [1, :left, :b],
|
||||
1 => [1, :stay, :halt]}
|
||||
}
|
||||
t = Turing.new([0, 1], # permitted symbols
|
||||
0, # blank symbol
|
||||
:a, # starting state
|
||||
[:halt], # terminating states
|
||||
[:a, :b, :c], # running states
|
||||
busy_beaver_rules, # operating rules
|
||||
[]) # starting tape
|
||||
print t.run, "\n"
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
proc turing {states initial terminating symbols blank tape rules {doTrace 1}} {
|
||||
set state $initial
|
||||
set idx 0
|
||||
set tape [split $tape ""]
|
||||
if {[llength $tape] == 0} {
|
||||
set tape [list $blank]
|
||||
}
|
||||
foreach rule $rules {
|
||||
lassign $rule state0 sym0 sym1 move state1
|
||||
set R($state0,$sym0) [list $sym1 $move $state1]
|
||||
}
|
||||
while {$state ni $terminating} {
|
||||
set sym [lindex $tape $idx]
|
||||
lassign $R($state,$sym) sym1 move state1
|
||||
if {$doTrace} {
|
||||
### Print the state, great for debugging
|
||||
puts "[join $tape ""]\t$state->$state1"
|
||||
puts "[string repeat { } $idx]^"
|
||||
}
|
||||
lset tape $idx $sym1
|
||||
switch $move {
|
||||
left {
|
||||
if {[incr idx -1] < 0} {
|
||||
set idx 0
|
||||
set tape [concat [list $blank] $tape]
|
||||
}
|
||||
}
|
||||
right {
|
||||
if {[incr idx] == [llength $tape]} {
|
||||
lappend tape $blank
|
||||
}
|
||||
}
|
||||
}
|
||||
set state $state1
|
||||
}
|
||||
return [join $tape ""]
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
puts "Simple incrementer"
|
||||
puts TAPE=[turing {q0 qf} q0 qf {1 B} B "111" {
|
||||
{q0 1 1 right q0}
|
||||
{q0 B 1 stay qf}
|
||||
}]
|
||||
puts "Three-state busy beaver"
|
||||
puts TAPE=[turing {a b c halt} a halt {0 1} 0 "" {
|
||||
{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}
|
||||
}]
|
||||
puts "Sorting stress test"
|
||||
# We suppress the trace output for this so as to keep the output short
|
||||
puts TAPE=[turing {A B C D E H} A H {0 1 2 3} 0 "12212212121212" {
|
||||
{A 1 1 right A}
|
||||
{A 2 3 right B}
|
||||
{A 0 0 left E}
|
||||
{B 1 1 right B}
|
||||
{B 2 2 right B}
|
||||
{B 0 0 left C}
|
||||
{C 1 2 left D}
|
||||
{C 2 2 left C}
|
||||
{C 3 2 left E}
|
||||
{D 1 1 left D}
|
||||
{D 2 2 left D}
|
||||
{D 3 1 right A}
|
||||
{E 1 1 left E}
|
||||
{E 0 0 right H}
|
||||
} no]
|
||||
Loading…
Add table
Add a link
Reference in a new issue