turing_machine 0.0.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6270dca8cb1652af9e145537e52bb199d0cd7190
4
- data.tar.gz: 3f57b50ac59a9849fe4d59640d166aeaf8166446
3
+ metadata.gz: 6343fe9455c4501953afaaefc30d0705f348528a
4
+ data.tar.gz: 662f0eedd0069a630a6d3ac22a1cd3fa1a895b15
5
5
  SHA512:
6
- metadata.gz: 440063906e7969e16d560a98878e9ee2e3eb85916ffd06cb60cf438d6d4d7b836b6693da4e07d9edc607b509c2445d1104ae5b453d18a36f0c9ff527bbf56536
7
- data.tar.gz: fd2ee8011de8838ddb7ab259ae9b2ae2ed42d3664a2401202a4441e094cef67e4b5e974da29c651b334822db38cd2e0f043b045f86f86109149809fb72fdca23
6
+ metadata.gz: 40f2436cfdcc9da7fd82146e84fb81dbeb505914b6fa905b199cc091771b328cec3c8ed7d7b10cc2e43b8bc40d62f2c18ca4de10d2296678fa83191af83fdcc3
7
+ data.tar.gz: 3a67ca0e6a8bad420e241bc974979d627c2ccb45691be3a4af4d02d3a9c5f3c71e2b11d508452243289a2203c2d511c1f4afe529908bea2dbdac25a85d6ab798
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --format documentation
2
2
  --color
3
+ --order=random
data/README.md CHANGED
@@ -6,9 +6,7 @@ TuringMachine
6
6
 
7
7
  ![Photo of Alan Turing](alan-turing2.jpg)
8
8
 
9
- Currently, in version 0.0.2, you could just run the hardcoded 3 states busy beaver
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
- $ turing_machine
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/[my-github-username]/turing_machine/fork )
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
- instructions = {
8
- ['0', 'A'] => {write: '1', move: 'R', next_state: 'B'},
9
- ['1', 'A'] => {write: '1', move: 'L', next_state: 'C'},
10
- ['0', 'B'] => {write: '1', move: 'L', next_state: 'A'},
11
- ['1', 'B'] => {write: '1', move: 'R', next_state: 'B'},
12
- ['0', 'C'] => {write: '1', move: 'L', next_state: 'B'},
13
- ['1', 'C'] => {write: '1', move: 'R', next_state: 'HALT'},
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
@@ -0,0 +1,4 @@
1
+ 0 A => 1 R B
2
+ 1 A => 1 L B
3
+ 0 B => 1 L A
4
+ 1 B => 1 R HALT
@@ -0,0 +1,6 @@
1
+ 0 A => 1 R B
2
+ 1 A => 1 L C
3
+ 0 B => 1 L A
4
+ 1 B => 1 R B
5
+ 0 C => 1 L B
6
+ 1 C => 1 R HALT
@@ -0,0 +1,6 @@
1
+ 0 A => 1 R B
2
+ 1 A => 1 R HALT
3
+ 0 B => 1 L B
4
+ 1 B => 0 R C
5
+ 0 C => 1 L C
6
+ 1 C => 1 L A
@@ -0,0 +1,8 @@
1
+ 0 A => 1 R B
2
+ 1 A => 1 L B
3
+ 0 B => 1 L A
4
+ 1 B => 0 L C
5
+ 0 C => 1 R HALT
6
+ 1 C => 1 L D
7
+ 0 D => 1 R D
8
+ 1 D => 0 R A
@@ -0,0 +1,13 @@
1
+ 0 A => 1 L B
2
+ 0 B => 1 L C
3
+ 0 C => 1 N s1
4
+ 0 s1 => N N HALT
5
+ 1 s1 => 0 R s2
6
+ 0 s2 => 0 R s3
7
+ 1 s2 => 1 R s2
8
+ 0 s3 => 1 L s4
9
+ 1 s3 => 1 R s3
10
+ 0 s4 => 0 L s5
11
+ 1 s4 => 1 L s4
12
+ 0 s5 => 1 R s1
13
+ 1 s5 => 1 L s5
@@ -0,0 +1,3 @@
1
+ 0 A => 1 R B
2
+ 0 B => 0 R C
3
+ 0 C => 1 R HALT
@@ -4,7 +4,7 @@ module TuringMachine
4
4
  class Instance
5
5
 
6
6
  def initialize(instructions, initial_state)
7
- @instruction = Instruction.new(instructions)
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' ? @tape.shift_left : @tape.shift_right
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
- @instruction.for(@tape.head, @state.current)
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 Instruction
4
+ class Instructions
5
5
 
6
6
  def initialize(table)
7
7
  @table = table
8
8
  end
9
9
 
10
- def for(symbol, state)
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
@@ -6,8 +6,8 @@ module TuringMachine
6
6
  def initialize
7
7
  # @symbols = [ '0' ]
8
8
  # @index = 0
9
- @symbols = Array.new(10) { '0' }
10
- @index = 4
9
+ @symbols = Array.new(40) { '0' }
10
+ @index = 19
11
11
  end
12
12
 
13
13
  attr_reader :index
@@ -1,3 +1,3 @@
1
1
  module TuringMachine
2
- VERSION = "0.0.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -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/instruction'
4
+ require 'turing_machine/instructions'
5
+ require 'turing_machine/instructions_parser'
5
6
  require 'turing_machine/instance'
6
7
 
7
8
  module TuringMachine
@@ -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 0000000000 A -> 1RB\n" +
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 0000100000 B -> 1LA\n" +
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 0000100000 HALT\n" +
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 Instruction do
5
+ describe Instructions do
6
6
 
7
- let(:instruction) do
8
- Instruction.new({
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 = instruction.for('0', 'A')
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
@@ -44,7 +44,7 @@ describe Tape do
44
44
  end
45
45
 
46
46
  it 'has a string representation' do
47
- expect("#{tape}").to eq '0000000000'
47
+ expect("#{tape}").to eq '0' * 40
48
48
  end
49
49
 
50
50
  end
@@ -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.2
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-01 00:00:00.000000000 Z
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/instruction.rb
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/instruction_spec.rb
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/instruction_spec.rb
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