Time for an 2014 update…

This commit is contained in:
Ingy döt Net 2014-01-17 05:32:22 +00:00
parent 372c577f83
commit 09687c4926
2520 changed files with 34227 additions and 7318 deletions

View file

@ -0,0 +1,243 @@
import std.stdio, std.algorithm, std.string, std.conv, std.array,
std.exception, std.traits, std.math, std.range;
struct UTM(State, Symbol, bool doShow=true)
if (is(State == enum) && is(Symbol == enum)) {
static assert(is(typeof({ size_t x = State.init; })),
"State must to be usable as array index.");
static assert([EnumMembers!State]
.equal(EnumMembers!State.length.iota),
"State must be a plain enum.");
static assert(is(typeof({ size_t x = Symbol.init; })),
"Symbol must to be usable as array index.");
static assert([EnumMembers!Symbol]
.equal(EnumMembers!Symbol.length.iota),
"Symbol must be a plain enum.");
enum Direction { right, left, stay }
private const TuringMachine tm;
private TapeHead head;
alias SymbolMap = string[EnumMembers!Symbol.length];
// The first index of this 'rules' matrix is a subtype of State
// because it can't contain H, but currently D can't enforce this,
// statically unlike Ada language.
Rule[EnumMembers!Symbol.length]
[EnumMembers!State.length - 1] mRules;
static struct Rule {
Symbol toWrite;
Direction direction;
State nextState;
this(in Symbol toWrite_, in Direction direction_,
in State nextState_) pure nothrow {
this.toWrite = toWrite_;
this.direction = direction_;
this.nextState = nextState_;
}
}
// This is kept separated from the rest so it can be inialized
// one field at a time in the main function, yet it will become
// const.
static struct TuringMachine {
Symbol blank;
State initialState;
Rule[Symbol][State] rules;
Symbol[] input;
SymbolMap symbolMap;
}
static struct TapeHead {
immutable Symbol blank;
Symbol[] tapeLeft, tapeRight;
int position;
const SymbolMap sMap;
size_t nSteps;
this(in ref TuringMachine t) pure /*nothrow*/ {
this.blank = EnumMembers!Symbol[0];
//tapeRight = t.input.empty ? [this.blank] : t.input.dup;
if (t.input.empty)
this.tapeRight = [this.blank];
else
this.tapeRight = t.input.dup; // Not nothrow.
this.position = 0;
this.sMap = t.symbolMap;
}
pure nothrow invariant() {
assert(this.tapeRight.length > 0);
if (this.position >= 0)
assert(this.position < this.tapeRight.length);
else
assert(this.position.abs <= this.tapeLeft.length);
}
Symbol readSymb() const pure nothrow {
if (this.position >= 0)
return this.tapeRight[this.position];
else
return this.tapeLeft[this.position.abs - 1];
}
void showSymb() const {
this.write;
}
void writeSymb(in Symbol symbol) {
static if (doShow)
showSymb;
if (this.position >= 0)
this.tapeRight[this.position] = symbol;
else
this.tapeLeft[this.position.abs - 1] = symbol;
}
void goRight() pure nothrow {
this.position++;
if (position > 0 && position == tapeRight.length)
tapeRight ~= blank;
}
void goLeft() pure nothrow {
this.position--;
if (position < 0 && (position.abs - 1) == tapeLeft.length)
tapeLeft ~= blank;
}
void move(in Direction dir) pure nothrow {
nSteps++;
final switch (dir) with (Direction) {
case left: goLeft; break;
case right: goRight; break;
case stay: /*Do nothing*/ break;
}
}
string toString() const {
const pos = cast(int)tapeLeft.length + this.position + 4;
return format("...%-(%)...", tapeLeft.retro
.chain(tapeRight)
.map!(s => sMap[s])) ~
'\n' ~
format("%" ~ pos.text ~ "s", "^") ~
'\n';
}
}
void show() const {
head.showSymb;
}
this(in ref TuringMachine tm_) {
static assert(__traits(compiles, State.H),
"State needs a 'H' (Halt).");
immutable errMsg = "Invalid input.";
auto runningStates = remove!(s => s == State.H)
([EnumMembers!State]);
enforce(!runningStates.empty, errMsg);
enforce(tm_.rules.length == EnumMembers!State.length - 1,
errMsg);
enforce(State.H !in tm_.rules, errMsg);
enforce(runningStates.canFind(tm_.initialState), errMsg);
// Create a matrix to reduce running time.
foreach (const State st, const rset; tm_.rules)
foreach (const Symbol sy, const rule; rset)
mRules[st][sy] = rule;
this.tm = tm_;
head = TapeHead(this.tm);
State state = tm.initialState;
while (state != State.H) {
immutable next = mRules[state][head.readSymb];
head.writeSymb(next.toWrite);
head.move(next.direction);
state = next.nextState;
}
static if (doShow)
show;
writeln("Performed ", head.nSteps, " steps.");
}
}
void main() {
"Incrementer:".writeln;
enum States1 : ubyte { A, H }
enum Symbols1 : ubyte { s0, s1 }
alias M1 = UTM!(States1, Symbols1);
M1.TuringMachine tm1;
with (tm1) with (States1) with (Symbols1) with (M1.Direction) {
alias R = M1.Rule;
initialState = A;
rules = [A: [s0: R(s1, stay, H), s1: R(s1, right, A)]];
input = [s1, s1, s1];
symbolMap = ["0", "1"];
}
M1(tm1);
// http://en.wikipedia.org/wiki/Busy_beaver
"\nBusy Beaver machine (3-state, 2-symbol):".writeln;
enum States2 : ubyte { A, B, C, H }
alias Symbols2 = Symbols1;
alias M2 = UTM!(States2, Symbols2);
M2.TuringMachine tm2;
with (tm2) with (States2) with (Symbols2) with (M2.Direction) {
alias R = M2.Rule;
initialState = A;
rules = [A: [s0: R(s1, right, B), s1: R(s1, left, C)],
B: [s0: R(s1, left, A), s1: R(s1, right, B)],
C: [s0: R(s1, left, B), s1: R(s1, stay, H)]];
symbolMap = ["0", "1"];
}
M2(tm2);
"\nSorting stress test (12212212121212):".writeln;
enum States3 : ubyte { A, B, C, D, E, H }
enum Symbols3 : ubyte { s0, s1, s2, s3 }
alias M3 = UTM!(States3, Symbols3, false);
M3.TuringMachine tm3;
with (tm3) with (States3) with (Symbols3) with (M3.Direction) {
alias R = M3.Rule;
initialState = A;
rules = [A: [s1: R(s1, right, A),
s2: R(s3, right, B),
s0: R(s0, left, E)],
B: [s1: R(s1, right, B),
s2: R(s2, right, B),
s0: R(s0, left, C)],
C: [s1: R(s2, left, D),
s2: R(s2, left, C),
s3: R(s2, left, E)],
D: [s1: R(s1, left, D),
s2: R(s2, left, D),
s3: R(s1, right, A)],
E: [s1: R(s1, left, E),
s0: R(s0, stay, H)]];
input = [s1, s2, s2, s1, s2, s2, s1,
s2, s1, s2, s1, s2, s1, s2];
symbolMap = ["0", "1", "2", "3"];
}
M3(tm3).show;
"\nPossible best Busy Beaver machine (5-state, 2-symbol):".writeln;
alias States4 = States3;
alias Symbols4 = Symbols1;
alias M4 = UTM!(States4, Symbols4, false);
M4.TuringMachine tm4;
with (tm4) with (States4) with (Symbols4) with (M4.Direction) {
alias R = M4.Rule;
initialState = A;
rules = [A: [s0: R(s1, right, B), s1: R(s1, left, C)],
B: [s0: R(s1, right, C), s1: R(s1, right, B)],
C: [s0: R(s1, right, D), s1: R(s0, left, E)],
D: [s0: R(s1, left, A), s1: R(s1, left, D)],
E: [s0: R(s1, stay, H), s1: R(s0, left, A)]];
symbolMap = ["0", "1"];
}
M4(tm4);
}

View file

@ -0,0 +1,52 @@
import std.stdio, std.typecons, std.array, std.algorithm, std.string;
void turing(Sy, St)(in Sy[] symbols, in Sy blank, in St initialState,
in St[] haltStates, in St[] runningStates,
in Tuple!(Sy, string, St)[Sy][St] rules,
in Sy[] startingTape = []) {
Sy[int] tape;
foreach (i, sy; startingTape)
tape[i] = sy;
int pos = 0;
St state = initialState;
while (!haltStates.canFind(state)) {
//auto symbol = tape.setDefault(pos, blank);
if (pos !in tape)
tape[pos] = blank;
auto symbol = tape[pos];
tape.keys.sort()
.map!(i => format(["%s", "(%s)"][i == pos], tape[i]))
.join(" ").writeln;
//{const outsym, const action, state} = rules[state][symbol];
const r = rules[state][symbol];
state = r[2];
tape[pos] = r[0];
pos += ["left": -1, "stay": 0, "right": 1][r[1]];
}
}
void main() {
alias t = tuple;
turing(['b', '1'], // Permitted symbols.
'b', // Blank symbol.
"q0", // Starting state.
["qf"], // Terminating states.
["q0"], // Running states.
// Operating rules.
["q0": ['1': t('1', "right", "q0"),
'b': t('1', "stay", "qf")]],
['1', '1', '1']); // Starting tape.
writeln;
turing([0, 1], // Permitted symbols.
0, // Blank symbol.
"a", // Starting state.
["halt"], // Terminating states.
["a", "b", "c"], // Running states.
// Operating rules.
["a": [0: t(1, "right", "b"), 1: t(1, "left", "c")],
"b": [0: t(1, "left", "a"), 1: t(1, "right", "b")],
"c": [0: t(1, "left", "b"), 1: t(1, "stay", "halt")]]);
}

View file

@ -1,190 +0,0 @@
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();
}
}