-
Notifications
You must be signed in to change notification settings - Fork 0
/
turing-machine.php
executable file
·127 lines (108 loc) · 2.85 KB
/
turing-machine.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/php
<?php
// Begin with state globals
$TAPE = [];
$CURRENT_POS = 0;
$CHECKSUM = NULL;
$STATE = [];
$CURRENT_STATE = NULL;
// Type definitions
class Action {
public $value;
public $movement;
public $next_state;
public function __construct(int $v, int $m, string $ns) {
$this->value = $v;
$this->movement = $m;
$this->next_state = $ns;
}
}
class State {
public $letter;
public $when_0;
public $when_1;
public function __construct(string $l, Action $a0, Action $a1) {
$this->letter = $l;
$this->when_0 = $a0;
$this->when_1 = $a1;
}
}
function str_starts_with($long, $short) {
return substr($long, 0, strlen($short)) === $short;
}
function parse_state_input($name) {
$act1 = $act2 = NULL;
$cval = $a_val = $a_mov = $a_ns = NULL;
while(1) {
$line = fgets(STDIN);
if($line === FALSE) {
fprintf(STDERR, "Unexpected end of data when parsing state\n");
die;
}
$line = trim($line);
if(str_starts_with($line, 'If the current value is ')) {
$cval = (int)substr($line, -2, 1);
} else if(str_starts_with($line, '- Write the value ')) {
$a_val = (int)substr($line, -2, 1);
} else if(str_starts_with($line, '- Continue with state ')) {
$a_ns = substr($line, -2, 1);
} else if($line === '- Move one slot to the left.') {
$a_mov = -1;
} else if($line === '- Move one slot to the right.') {
$a_mov = +1;
} else {
fprintf(STDERR, "parse_state_input(): Unrecognized input: \"%s\"\n", $line);
die;
}
if(($cval !== NULL) && ($a_val !== NULL) && ($a_mov !== NULL) && ($a_ns !== NULL)) {
if($cval === 0)
$act0 = new Action($a_val, $a_mov, $a_ns);
else
$act1 = new Action($a_val, $a_mov, $a_ns);
if(($act0 !== NULL) && ($act1 !== NULL)) {
return new State($name, $act0, $act1);
}
$cval = $a_val = $a_mov = $a_ns = NULL;
}
}
}
function parse_input() {
global $STATE;
global $CURRENT_STATE;
global $CHECKSUM;
while(1) {
$line = fgets(STDIN);
if($line === FALSE) return;
$line = trim($line);
if(str_starts_with($line, 'Begin in state ')) {
$CURRENT_STATE = substr($line, -2, 1);
} else if(str_starts_with($line, 'Perform a diagnostic checksum after ')) {
$CHECKSUM = (int)preg_replace('/[^0-9]/', '', $line);
} else if(str_starts_with($line, 'In state ')) {
$statename = substr($line, -2, 1);
$STATE[$statename] = parse_state_input($statename);
} else if($line === '') {
// nothing to do
} else {
fprintf(STDERR, "parse_input(): Unrecognized input: \"%s\"\n", $line);
die;
}
}
}
// Time for program code proper
parse_input();
while($CHECKSUM --> 0) {
$st = $STATE[$CURRENT_STATE];
$act;
$cur_val = $TAPE[$CURRENT_POS] ?? 0;
if($cur_val === 0) {
$act = $st->when_0;
} else {
$act = $st->when_1;
}
$TAPE[$CURRENT_POS] = $act->value;
$CURRENT_POS += $act->movement;
$CURRENT_STATE = $act->next_state;
}
echo array_sum($TAPE);
echo "\n";