turing_machine 0.0.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/README.md +10 -5
- data/bin/turing_machine +15 -8
- data/instruction_sets/README.md +9 -0
- data/instruction_sets/busy_beaver_1 +1 -0
- data/instruction_sets/busy_beaver_2 +4 -0
- data/instruction_sets/busy_beaver_3 +6 -0
- data/instruction_sets/busy_beaver_3-2 +6 -0
- data/instruction_sets/busy_beaver_4 +8 -0
- data/instruction_sets/copy_with_data +13 -0
- data/instruction_sets/write101 +3 -0
- data/lib/turing_machine/instance.rb +5 -4
- data/lib/turing_machine/{instruction.rb → instructions.rb} +2 -2
- data/lib/turing_machine/instructions_parser.rb +55 -0
- data/lib/turing_machine/tape.rb +2 -2
- data/lib/turing_machine/version.rb +1 -1
- data/lib/turing_machine.rb +2 -1
- data/spec/instance_spec.rb +33 -6
- data/spec/instructions_parser_spec.rb +39 -0
- data/spec/{instruction_spec.rb → instructions_spec.rb} +4 -4
- data/spec/tape_spec.rb +1 -1
- data/turing_machine.gemspec +2 -2
- metadata +18 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6343fe9455c4501953afaaefc30d0705f348528a
|
4
|
+
data.tar.gz: 662f0eedd0069a630a6d3ac22a1cd3fa1a895b15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40f2436cfdcc9da7fd82146e84fb81dbeb505914b6fa905b199cc091771b328cec3c8ed7d7b10cc2e43b8bc40d62f2c18ca4de10d2296678fa83191af83fdcc3
|
7
|
+
data.tar.gz: 3a67ca0e6a8bad420e241bc974979d627c2ccb45691be3a4af4d02d3a9c5f3c71e2b11d508452243289a2203c2d511c1f4afe529908bea2dbdac25a85d6ab798
|
data/.rspec
CHANGED
data/README.md
CHANGED
@@ -6,9 +6,7 @@ TuringMachine
|
|
6
6
|
|
7
7
|

|
8
8
|
|
9
|
-
|
10
|
-
algorithm. There is nothing to tweak.
|
11
|
-
I wish to be able to run any instruction sets in a very near future.
|
9
|
+
A Turing machine that can run (almost) (one day maybe) (I hope) any instruction set.
|
12
10
|
|
13
11
|
## Installation
|
14
12
|
|
@@ -18,11 +16,18 @@ Install it with:
|
|
18
16
|
|
19
17
|
## Usage
|
20
18
|
|
21
|
-
|
19
|
+
Look at some well-known instruction sets in [instruction_sets](instruction_sets)
|
20
|
+
or create your own. Then run the Turing machine with, for example:
|
21
|
+
|
22
|
+
$ turing_machine instruction_sets/busy_beaver_1
|
23
|
+
|
24
|
+
Look at the
|
25
|
+
[InstructionsParser class](lib/turing_machine/instructions_parser.rb) for a
|
26
|
+
documentation of the instruction format.
|
22
27
|
|
23
28
|
## Contributing
|
24
29
|
|
25
|
-
1. Fork it ( https://github.com/
|
30
|
+
1. Fork it ( https://github.com/lkdjiin/turing_machine/fork )
|
26
31
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
32
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
33
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/bin/turing_machine
CHANGED
@@ -4,19 +4,26 @@ require 'turing_machine'
|
|
4
4
|
|
5
5
|
include TuringMachine
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
[
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
if ARGV[0].nil?
|
8
|
+
exit(1)
|
9
|
+
else
|
10
|
+
filename = ARGV[0]
|
11
|
+
end
|
12
|
+
|
13
|
+
if File.exist?(filename)
|
14
|
+
raw_instructions = IO.read(filename)
|
15
|
+
else
|
16
|
+
exit(2)
|
17
|
+
end
|
18
|
+
|
19
|
+
parser = InstructionsParser.new(raw_instructions)
|
20
|
+
instructions = parser.parse
|
15
21
|
|
16
22
|
initial_state = 'A'
|
17
23
|
|
18
24
|
instance = Instance.new(instructions, initial_state)
|
19
25
|
|
26
|
+
# This should be testable.
|
20
27
|
loop do
|
21
28
|
puts instance.to_s
|
22
29
|
break if instance.halted?
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Examples of instruction sets for the Turing machine
|
2
|
+
===================================================
|
3
|
+
|
4
|
+
- `busy_beaver_1` : Busy beaver one state
|
5
|
+
- `busy_beaver_2` : Busy beaver two states
|
6
|
+
- `busy_beaver_3` : Busy beaver three states
|
7
|
+
- `busy_beaver_3-2` : Another busy beaver three states
|
8
|
+
- `busy_beaver_4` : Busy beaver four states
|
9
|
+
- `write101` : Write the number 101
|
@@ -0,0 +1 @@
|
|
1
|
+
0 A => 1 R HALT
|
@@ -4,7 +4,7 @@ module TuringMachine
|
|
4
4
|
class Instance
|
5
5
|
|
6
6
|
def initialize(instructions, initial_state)
|
7
|
-
@
|
7
|
+
@instructions = Instructions.new(instructions)
|
8
8
|
@state = StateRegister.new(initial_state)
|
9
9
|
@tape = Tape.new
|
10
10
|
@sequence = 1
|
@@ -33,8 +33,9 @@ module TuringMachine
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def update_tape(current_action)
|
36
|
-
@tape.head = current_action[:write]
|
37
|
-
current_action[:move] == 'L'
|
36
|
+
@tape.head = current_action[:write] unless current_action[:write] == 'N'
|
37
|
+
@tape.shift_left if current_action[:move] == 'L'
|
38
|
+
@tape.shift_right if current_action[:move] == 'R'
|
38
39
|
end
|
39
40
|
|
40
41
|
def update_state(current_action)
|
@@ -42,7 +43,7 @@ module TuringMachine
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def action
|
45
|
-
@
|
46
|
+
@instructions.get(@tape.head, @state.current)
|
46
47
|
end
|
47
48
|
|
48
49
|
def instr_to_s
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module TuringMachine
|
2
2
|
|
3
3
|
# Public: The instruction table of a Turing machine.
|
4
|
-
class
|
4
|
+
class Instructions
|
5
5
|
|
6
6
|
def initialize(table)
|
7
7
|
@table = table
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
10
|
+
def get(symbol, state)
|
11
11
|
@table[[symbol, state]]
|
12
12
|
end
|
13
13
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module TuringMachine
|
2
|
+
|
3
|
+
# Public: Parser for a newline separated instruction set.
|
4
|
+
#
|
5
|
+
# Instruction format
|
6
|
+
# ------------------
|
7
|
+
#
|
8
|
+
# Here is an example file with four instructions :
|
9
|
+
#
|
10
|
+
# ```
|
11
|
+
# 0 A => 1 R B
|
12
|
+
# 1 A => 1 L B
|
13
|
+
# 0 B => 1 L A
|
14
|
+
# 1 B => 1 R HALT
|
15
|
+
# ```
|
16
|
+
#
|
17
|
+
# So each instruction is :
|
18
|
+
#
|
19
|
+
# ```
|
20
|
+
# scanned-symbol current-state => symbol-to-write move next-state
|
21
|
+
# ```
|
22
|
+
#
|
23
|
+
# `symbol-to-write` is usually `1` or `0`. Note that `N` is a special
|
24
|
+
# symbol meaning «write nothing».
|
25
|
+
#
|
26
|
+
# `move` could be either `L` for left, `R` for right, or `N` for no
|
27
|
+
# movement.
|
28
|
+
class InstructionsParser
|
29
|
+
|
30
|
+
def initialize(raw_instructions)
|
31
|
+
@lines = raw_instructions.split("\n")
|
32
|
+
@instructions = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse
|
36
|
+
build_instructions
|
37
|
+
@instructions
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def build_instructions
|
43
|
+
@lines.each do |instruction|
|
44
|
+
keys, value = instruction.split('=>')
|
45
|
+
key_symbol, key_state = keys.split
|
46
|
+
write, move, next_state = value.split
|
47
|
+
@instructions[[key_symbol, key_state]] = {
|
48
|
+
write: write, move: move, next_state: next_state
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/lib/turing_machine/tape.rb
CHANGED
data/lib/turing_machine.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require "turing_machine/version"
|
2
2
|
require 'turing_machine/tape'
|
3
3
|
require 'turing_machine/state_register'
|
4
|
-
require 'turing_machine/
|
4
|
+
require 'turing_machine/instructions'
|
5
|
+
require 'turing_machine/instructions_parser'
|
5
6
|
require 'turing_machine/instance'
|
6
7
|
|
7
8
|
module TuringMachine
|
data/spec/instance_spec.rb
CHANGED
@@ -16,19 +16,46 @@ initial_state = 'A'
|
|
16
16
|
describe Instance do
|
17
17
|
it 'produces an output' do
|
18
18
|
instance = Instance.new(instructions, initial_state)
|
19
|
-
expected = " 1
|
20
|
-
"
|
19
|
+
expected = " 1 0000000000000000000000000000000000000000 A -> 1RB\n" +
|
20
|
+
" ^"
|
21
21
|
expect(instance.to_s).to eq expected
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'computes a step' do
|
25
25
|
instance = Instance.new(instructions, initial_state)
|
26
26
|
instance.proceed
|
27
|
-
expected = " 2
|
28
|
-
"
|
27
|
+
expected = " 2 0000000000000000000100000000000000000000 B -> 1LA\n" +
|
28
|
+
" ^"
|
29
29
|
expect(instance.to_s).to eq expected
|
30
30
|
end
|
31
31
|
|
32
|
+
describe 'null movement' do
|
33
|
+
it 'does not move the head' do
|
34
|
+
instructions = {
|
35
|
+
['0', 'A'] => {write: '1', move: 'N', next_state: 'HALT'}
|
36
|
+
}
|
37
|
+
instance = Instance.new(instructions, initial_state)
|
38
|
+
instance.proceed
|
39
|
+
expected = " 2 0000000000000000000100000000000000000000 HALT\n" +
|
40
|
+
" ^"
|
41
|
+
expect(instance.to_s).to eq expected
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'null write' do
|
46
|
+
it 'does not write the current cell' do
|
47
|
+
instructions = {
|
48
|
+
['0', 'A'] => {write: 'N', move: 'N', next_state: 'HALT'}
|
49
|
+
}
|
50
|
+
instance = Instance.new(instructions, initial_state)
|
51
|
+
instance.proceed
|
52
|
+
expected = " 2 0000000000000000000000000000000000000000 HALT\n" +
|
53
|
+
" ^"
|
54
|
+
expect(instance.to_s).to eq expected
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
32
59
|
context 'when halted' do
|
33
60
|
|
34
61
|
it 'tells if the machine is halted' do
|
@@ -47,8 +74,8 @@ describe Instance do
|
|
47
74
|
}
|
48
75
|
instance = Instance.new(instructions, initial_state)
|
49
76
|
instance.proceed
|
50
|
-
expected = " 2
|
51
|
-
"
|
77
|
+
expected = " 2 0000000000000000000100000000000000000000 HALT\n" +
|
78
|
+
" ^"
|
52
79
|
expect(instance.to_s).to eq expected
|
53
80
|
end
|
54
81
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include TuringMachine
|
4
|
+
|
5
|
+
describe InstructionsParser do
|
6
|
+
|
7
|
+
let(:busy_beaver_1) { "0 A => 1 R HALT" }
|
8
|
+
|
9
|
+
let(:busy_beaver_2) do
|
10
|
+
"0 A => 1 R B\n1 A => 1 L B\n0 B => 1 L A\n1 B => 1 R HALT"
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#parse' do
|
14
|
+
it 'returns Instruction' do
|
15
|
+
parser = InstructionsParser.new(busy_beaver_1)
|
16
|
+
value = parser.parse
|
17
|
+
expect(value).to be_a Hash
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when parsing busy beaver 1 state' do
|
22
|
+
it 'parses the single instruction' do
|
23
|
+
parser = InstructionsParser.new(busy_beaver_1)
|
24
|
+
value = parser.parse
|
25
|
+
expected = {write: '1', move: 'R', next_state: 'HALT'}
|
26
|
+
expect(value[['0', 'A']]).to eq expected
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when parsing busy beaver 2 states' do
|
31
|
+
it 'parses all four instructions' do
|
32
|
+
parser = InstructionsParser.new(busy_beaver_2)
|
33
|
+
value = parser.parse
|
34
|
+
expected = {write: '1', move: 'R', next_state: 'HALT'}
|
35
|
+
expect(value[['1', 'B']]).to eq expected
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -2,17 +2,17 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
include TuringMachine
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe Instructions do
|
6
6
|
|
7
|
-
let(:
|
8
|
-
|
7
|
+
let(:instructions) do
|
8
|
+
Instructions.new({
|
9
9
|
['0', 'A'] => {write: '1', move: 'R', next_state: 'B'},
|
10
10
|
['1', 'A'] => {write: '1', move: 'L', next_state: 'C'},
|
11
11
|
})
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'finds actions' do
|
15
|
-
hash =
|
15
|
+
hash = instructions.get('0', 'A')
|
16
16
|
expect(hash[:write]).to eq '1'
|
17
17
|
expect(hash[:move]).to eq 'R'
|
18
18
|
expect(hash[:next_state]).to eq 'B'
|
data/spec/tape_spec.rb
CHANGED
data/turing_machine.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = TuringMachine::VERSION
|
9
9
|
spec.authors = ["Xavier Nayrac"]
|
10
10
|
spec.email = ["xavier.nayrac@gmail.com"]
|
11
|
-
spec.summary = %q{Turing machine}
|
12
|
-
spec.description = %q{Turing machine}
|
11
|
+
spec.summary = %q{A Turing machine}
|
12
|
+
spec.description = %q{A Turing machine that can run your instruction set}
|
13
13
|
spec.homepage = "http://lkdjiin.github.com/turing_machine/"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turing_machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xavier Nayrac
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.12'
|
97
|
-
description: Turing machine
|
97
|
+
description: A Turing machine that can run your instruction set
|
98
98
|
email:
|
99
99
|
- xavier.nayrac@gmail.com
|
100
100
|
executables:
|
@@ -112,14 +112,24 @@ files:
|
|
112
112
|
- Rakefile
|
113
113
|
- alan-turing2.jpg
|
114
114
|
- bin/turing_machine
|
115
|
+
- instruction_sets/README.md
|
116
|
+
- instruction_sets/busy_beaver_1
|
117
|
+
- instruction_sets/busy_beaver_2
|
118
|
+
- instruction_sets/busy_beaver_3
|
119
|
+
- instruction_sets/busy_beaver_3-2
|
120
|
+
- instruction_sets/busy_beaver_4
|
121
|
+
- instruction_sets/copy_with_data
|
122
|
+
- instruction_sets/write101
|
115
123
|
- lib/turing_machine.rb
|
116
124
|
- lib/turing_machine/instance.rb
|
117
|
-
- lib/turing_machine/
|
125
|
+
- lib/turing_machine/instructions.rb
|
126
|
+
- lib/turing_machine/instructions_parser.rb
|
118
127
|
- lib/turing_machine/state_register.rb
|
119
128
|
- lib/turing_machine/tape.rb
|
120
129
|
- lib/turing_machine/version.rb
|
121
130
|
- spec/instance_spec.rb
|
122
|
-
- spec/
|
131
|
+
- spec/instructions_parser_spec.rb
|
132
|
+
- spec/instructions_spec.rb
|
123
133
|
- spec/spec_helper.rb
|
124
134
|
- spec/state_register_spec.rb
|
125
135
|
- spec/tape_spec.rb
|
@@ -148,10 +158,11 @@ rubyforge_project:
|
|
148
158
|
rubygems_version: 2.4.5
|
149
159
|
signing_key:
|
150
160
|
specification_version: 4
|
151
|
-
summary: Turing machine
|
161
|
+
summary: A Turing machine
|
152
162
|
test_files:
|
153
163
|
- spec/instance_spec.rb
|
154
|
-
- spec/
|
164
|
+
- spec/instructions_parser_spec.rb
|
165
|
+
- spec/instructions_spec.rb
|
155
166
|
- spec/spec_helper.rb
|
156
167
|
- spec/state_register_spec.rb
|
157
168
|
- spec/tape_spec.rb
|