rbtm 2.0.3

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.
Files changed (6) hide show
  1. checksums.yaml +7 -0
  2. data/bin/rbtm +49 -0
  3. data/bin/rbtm_rule +33 -0
  4. data/lib/rbtm.rb +37 -0
  5. data/lib/rbtm/head.rb +63 -0
  6. metadata +50 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 35b68522df47f8515925d555a836d3417cad65dd
4
+ data.tar.gz: e4c53e17100bf5ae40677ec24b9c6c39345d3734
5
+ SHA512:
6
+ metadata.gz: 5f4c3d8fd2ea001996f6eaeb29fc0896dade94ec88f377363756b66d87ab87ba4a2a0445a385fdf89f098d22fe4f2af706c424b9d82e3605a76fea9af25fe47c
7
+ data.tar.gz: bb8ca23db9178ad5e966f0625513323891b81349fd8b1c0016155cb24bcdfc211f60a189c4d28602ffd8fa95b3c29ed68123fdf44dbf248a59b0924a1d3fbff0
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rbtm'
3
+
4
+
5
+ def stop(reason)
6
+ puts reason
7
+ exit
8
+ end
9
+
10
+
11
+ begin
12
+ rule = ARGV.fetch(0)
13
+ tape = ARGV.fetch(1)
14
+ rescue
15
+ stop('Usage: rbtm <rule> <tape> [-v]')
16
+ end
17
+
18
+ VERBOSE = ARGV[2].to_s.include?('v')
19
+
20
+ stop('Rule file does not exist.') unless File.exists?(rule)
21
+
22
+ if File.exists?(tape)
23
+ tape = File.read(tape).strip
24
+ end
25
+
26
+ rules, state = Rbtm.parse(rule)
27
+ stop('No valid rules.') if rules.empty?
28
+ head = Rbtm::Head.new(tape, state)
29
+
30
+
31
+ if VERBOSE
32
+ print 'Seconds per frame? (default: 0.5) '
33
+ SLEEP_TIME = (num = $stdin.gets.to_f).zero? ? 0.5 : num
34
+ COLS = `tput cols`.to_i
35
+
36
+ system('clear')
37
+ Rbtm.turing_machine(rules, head) do |h|
38
+ first = (head.index / COLS) * COLS
39
+ puts "#{' ' * head.index}v"[first...(first + COLS)]
40
+ puts head.tape[first...(first + COLS)]
41
+ puts
42
+ puts head.state
43
+ sleep(SLEEP_TIME)
44
+ system('clear')
45
+ end
46
+ else
47
+ Rbtm.turing_machine(rules, head)
48
+ end
49
+ puts head
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ def stop(reason)
5
+ puts reason
6
+ exit
7
+ end
8
+
9
+
10
+ begin
11
+ file = ARGV.fetch(0)
12
+ rescue
13
+ stop('Usage: rbtm_rule <file>')
14
+ end
15
+
16
+
17
+ print 'States: '
18
+ states = $stdin.gets.split.uniq
19
+
20
+ print 'Alphabet: '
21
+ alphabet = $stdin.gets.strip.split(//).uniq
22
+ alphabet.map! { |c| c[0] }
23
+
24
+ File.open(file, 'w') do |f|
25
+ contents = ''
26
+
27
+ states.each do |s|
28
+ alphabet.each { |c| contents << "#{s}\t#{c}\n" }
29
+ contents << "\n"
30
+ end
31
+
32
+ f.write(contents)
33
+ end
@@ -0,0 +1,37 @@
1
+ module Rbtm
2
+
3
+ ##
4
+ # Regexp for matching rules.
5
+ REGEX = /\s*(\w+)\s+(\w)\s+(\w+)\s+(\w)\s+([LNR])/
6
+
7
+ ##
8
+ # Parses rules and start state from a file.
9
+ def self.parse(file)
10
+ rules = {}
11
+ state = nil
12
+
13
+ File.readlines(file).each do |line|
14
+ next unless line =~ REGEX
15
+
16
+ state ||= $1
17
+ rules[[$1, $2]] = [$3, $4, $5]
18
+ end
19
+
20
+ [rules, state]
21
+ end
22
+
23
+ ##
24
+ # Runs a Turing machine. Yields current head if given a block.
25
+ def self.turing_machine(rules, head)
26
+ loop do
27
+ rule = rules[head.signature]
28
+
29
+ yield head if block_given?
30
+ break unless rule
31
+
32
+ head.operate(rule)
33
+ end
34
+ end
35
+ end
36
+
37
+ require 'rbtm/head'
@@ -0,0 +1,63 @@
1
+ module Rbtm
2
+
3
+ ##
4
+ # The read/write head of the Turing machine.
5
+ class Head
6
+ attr_reader :index, :state, :tape
7
+
8
+ def initialize(str, state)
9
+ @tape = (str.empty? ? '_' : str.dup)
10
+ @state = state
11
+ @index = 0
12
+ end
13
+
14
+ ##
15
+ # Operates on the tape using the given rule.
16
+ def operate(rule)
17
+ @state = rule[0]
18
+ write(rule[1])
19
+
20
+ case rule[2]
21
+ when 'L'
22
+ left
23
+ when 'R'
24
+ right
25
+ end
26
+ end
27
+
28
+ def signature
29
+ [state, read]
30
+ end
31
+
32
+ def to_s
33
+ tape.sub(/^_+/, '').sub(/_+$/, '')
34
+ end
35
+
36
+ private
37
+
38
+ def left
39
+ if index.zero?
40
+ pad
41
+ else
42
+ @index -= 1
43
+ end
44
+ end
45
+
46
+ def pad
47
+ tape.insert(index, '_')
48
+ end
49
+
50
+ def read
51
+ tape[index]
52
+ end
53
+
54
+ def right
55
+ @index += 1
56
+ pad if index == tape.size
57
+ end
58
+
59
+ def write(char)
60
+ tape[index] = char
61
+ end
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbtm
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.3
5
+ platform: ruby
6
+ authors:
7
+ - loatbac
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-23 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple Turing machine gem for Ruby; type "rbtm" in bash to run, or
14
+ "rbtm_rule" to generate a rule template.
15
+ email:
16
+ executables:
17
+ - rbtm
18
+ - rbtm_rule
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - bin/rbtm
23
+ - bin/rbtm_rule
24
+ - lib/rbtm.rb
25
+ - lib/rbtm/head.rb
26
+ homepage: https://github.com/LoaTBaC/rbtm
27
+ licenses:
28
+ - MIT
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 2.6.4
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: A simple Turing machine for Ruby
50
+ test_files: []