fork download
  1. $null_symbol = '_'
  2.  
  3. code_example = """
  4. _ 1 => _ L 2
  5. _ 4 => _ N 0
  6. _ 5 => _ N 0
  7. a 1 => a R 1
  8. a 2 => a L 3
  9. a 3 => _ L 4
  10. a 4 => _ L 4
  11. a 5 => b L 5
  12. b 1 => b R 1
  13. b 2 => b L 3
  14. b 3 => b L 5
  15. b 4 => _ L 4
  16. b 5 => b L 5
  17. """ #"
  18.  
  19. code_311 = """
  20. a 1 => _ R 10
  21. b 1 => _ R 20
  22.  
  23. a 10 => a R 11
  24. a 20 => a R 21
  25. b 10 => b R 11
  26. b 20 => b R 21
  27. _ 10 => _ R 11
  28. _ 20 => _ R 21
  29.  
  30. a 11 => a R 12
  31. a 21 => a R 22
  32. b 11 => a R 12
  33. b 21 => a R 22
  34. _ 11 => a R 12
  35. _ 21 => a R 22
  36.  
  37. a 12 => a R 3
  38. a 22 => b R 3
  39. b 12 => a R 3
  40. b 22 => b R 3
  41. _ 12 => a R 3
  42. _ 22 => b R 3
  43.  
  44. a 3 => _ R 3
  45. b 3 => _ R 3
  46. _ 3 => _ N 0
  47. """ #"
  48.  
  49. code_312 = """
  50. 1 1 => 1 R 1
  51. _ 1 => S N 10
  52.  
  53. S 10 => S R 11
  54. _ 11 => _ L 30
  55. 1 11 => 1 L 12
  56. S 12 => S L 13
  57. _ 13 => _ R 20
  58. 1 13 => 1 R 14
  59. S 14 => S N 40
  60.  
  61. S 20 => _ R 21
  62. 1 21 => _ R 21
  63. _ 21 => _ N 0
  64.  
  65. S 30 => 1 L 31
  66. 1 31 => _ L 31
  67. _ 31 => _ N 0
  68.  
  69. S 40 => S L 41
  70. 1 41 => 1 L 41
  71. _ 41 => _ R 42
  72. 1 42 => _ R 43
  73. 1 43 => 1 R 43
  74. S 43 => S R 44
  75. 1 44 => 1 R 44
  76. _ 44 => _ L 45
  77. 1 45 => _ L 46
  78. 1 46 => 1 L 46
  79. S 46 => S N 10
  80. """ #"
  81.  
  82. code_313 = """
  83. 1 1 => _ R 1
  84. 1 2 => 1 R 2
  85. 1 3 => _ R 3
  86. 1 4 => _ L 5
  87. 1 5 => 1 L 5
  88. _ 1 => 1 R 2
  89. _ 2 => 1 R 3
  90. _ 3 => _ R 4
  91. _ 4 => _ L 4
  92. _ 5 => 1 L 6
  93. _ 6 => 1 L 0
  94. """ #"
  95.  
  96. class TuringMachine
  97. class TuringMachineWord
  98. attr_accessor :low_bound, :high_bound, :by_index
  99.  
  100. def initialize(wrd)
  101. @low_bound, @high_bound = 0, wrd.length-1
  102. @by_index = Hash.new
  103. wrd.length.times {|i| @by_index[i] = wrd[i]}
  104. end
  105.  
  106. def to_s
  107. res = []
  108. for i in (@low_bound-1..@high_bound+1) do
  109. res << (@by_index[i] || $null_symbol)
  110. end
  111. res.join ''
  112. end
  113.  
  114. def []=(key, value)
  115. @by_index[key] = value
  116. @low_bound = [@low_bound, key].min
  117. @high_bound = [@high_bound, key].max
  118. end
  119.  
  120. def [](key)
  121. @by_index[key]
  122. end
  123. end
  124.  
  125. attr_accessor :commands, :state, :word, :pos, :step_count, :finished
  126. attr_accessor :name
  127.  
  128. def initialize(name='Custom Turing machine')
  129. @commands = Hash.new
  130. @name = name
  131. end
  132.  
  133. def set_com(com)
  134. com = parse_com com
  135. unless com
  136. log 'Invalid command'
  137. return
  138. end
  139.  
  140. @commands[com[0]] = com[1]
  141. end
  142.  
  143. def log(msg='')
  144. puts "[TM] " + msg
  145. end
  146.  
  147. def run(wrd)
  148. @word = TuringMachineWord.new wrd
  149. @state, @pos, @step_count = 1, 0, 0
  150. @finished = false
  151.  
  152. log "Starting #{@name} on a word '#{wrd}'..."
  153. log "Initial:"
  154. log_step
  155.  
  156. step until @finished
  157.  
  158. log "Finished #{@name} run."
  159. end
  160.  
  161. private
  162. def parse_com(com)
  163. com = com.split(' => ').map &:split
  164. return false unless
  165. com.length == 2 &&
  166. com[0].length == 2 &&
  167. com[1].length == 3 &&
  168. /^[LNR]$/ =~ com[1][1]
  169.  
  170. com[1][1] = 'LNR'.index(com[1][1])-1
  171. 2.times {|i| com[i][-1] = com[i][-1].to_i}
  172. com
  173. end
  174.  
  175. def step
  176. com = @commands[[@word[@pos] || $null_symbol, @state]]
  177.  
  178. unless com
  179. log "No command for state [#{@word[@pos]}, #{@state}]"
  180. @finished = true
  181. return
  182. end
  183.  
  184. @word[@pos] = com[0]
  185. @pos += com[1]
  186. @state = com[2]
  187. @finished = true if @state == 0
  188.  
  189. @step_count += 1
  190. log "Step: #{@step_count}"
  191. log_step
  192. end
  193.  
  194. def log_step
  195. log @word.to_s
  196. log ' '*(@pos - @word.low_bound + 1) + "^ #{@state}"
  197. log
  198. end
  199.  
  200. end
  201.  
  202. puts """
  203. Turing machine emulator
  204.  
  205. Commands to enter must be in format:
  206. 'symbol state => new_symbol [LNR] new_state'
  207.  
  208. L - shift left, N - stay in position, R - shift right
  209. Null-symbol (lambda) is #{$null_symbol}
  210.  
  211. Choose Turing machine:
  212. 0) custom machine
  213. 1) 3.1.1 example (any [ab]+ word into [x(n) if x(n-1)=a else b*(n-1)+x(n)])
  214. 2) 3.1.1 variant 5 (any [ab]+ word into x(2)ax(1))
  215. 3) 3.1.2 variant 5 (f(x,y) => (x >= y) ? 1 : 0)
  216. 4) 3.1.3 variant 5 (set by table, x(2) + x(3) + 2)
  217. """ #"
  218.  
  219. case gets.strip
  220. when '1'
  221. tm = TuringMachine.new '3.1.1 example'
  222. code_example.each_line do |line|
  223. tm.set_com line.strip unless line.strip == ''
  224. end
  225. when '2'
  226. tm = TuringMachine.new 'variant 5 (3.1.1)'
  227. code_311.each_line do |line|
  228. tm.set_com line.strip unless line.strip == ''
  229. end
  230. when '3'
  231. tm = TuringMachine.new 'variant 5 (3.1.2)'
  232. code_312.each_line do |line|
  233. tm.set_com line.strip unless line.strip == ''
  234. end
  235. when '4'
  236. tm = TuringMachine.new 'variant 5 (3.1.3)'
  237. code_313.each_line do |line|
  238. tm.set_com line.strip unless line.strip == ''
  239. end
  240. when '0'
  241. tm = TuringMachine.new
  242. puts "Enter amount of commands and then list of commands:"
  243. gets.strip.to_i.times do |_|
  244. line = gets.strip
  245. tm.set_com line unless line == ''
  246. end
  247. else
  248. puts 'Invalid option'
  249. exit
  250. end
  251.  
  252. while true do
  253. puts "Enter word:"
  254. tm.run gets.strip
  255. end
Runtime error #stdin #stdout #stderr 0.01s 28688KB
stdin
4
1_1
stdout
Turing machine emulator

Commands to enter must be in format: 
    'symbol state => new_symbol [LNR] new_state'

L - shift left, N - stay in position, R - shift right
Null-symbol (lambda) is _

Choose Turing machine:
    0) custom machine
    1) 3.1.1 example (any [ab]+ word into [x(n) if x(n-1)=a else b*(n-1)+x(n)])
    2) 3.1.1 variant 5 (any [ab]+ word into x(2)ax(1))
    3) 3.1.2 variant 5 (f(x,y) => (x >= y) ? 1 : 0)
    4) 3.1.3 variant 5 (set by table, x(2) + x(3) + 2)
Enter word:
[TM] Starting variant 5 (3.1.3) on a word '1_1'...
[TM] Initial:
[TM] _1_1_
[TM]  ^ 1
[TM] 
[TM] Step: 1
[TM] ___1_
[TM]   ^ 1
[TM] 
[TM] Step: 2
[TM] __11_
[TM]    ^ 2
[TM] 
[TM] Step: 3
[TM] __11_
[TM]     ^ 2
[TM] 
[TM] Step: 4
[TM] __111_
[TM]      ^ 3
[TM] 
[TM] Step: 5
[TM] __111__
[TM]       ^ 4
[TM] 
[TM] Step: 6
[TM] __111___
[TM]      ^ 4
[TM] 
[TM] Step: 7
[TM] __111___
[TM]     ^ 4
[TM] 
[TM] Step: 8
[TM] __11____
[TM]    ^ 5
[TM] 
[TM] Step: 9
[TM] __11____
[TM]   ^ 5
[TM] 
[TM] Step: 10
[TM] __11____
[TM]  ^ 5
[TM] 
[TM] Step: 11
[TM] _111____
[TM] ^ 6
[TM] 
[TM] Step: 12
[TM] _1111____
[TM] ^ 0
[TM] 
[TM] Finished variant 5 (3.1.3) run.
Enter word:
stderr
prog.rb:254:in `<main>': undefined method `strip' for nil:NilClass (NoMethodError)