yatm 0.2.0 → 0.2.1
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/lib/yatm/error.rb +1 -0
- data/lib/yatm/machine/machine.rb +32 -2
- data/lib/yatm/state_machine/state_machine.rb +72 -7
- data/lib/yatm/tape/tape.rb +1 -0
- data/lib/yatm/version.rb +1 -1
- data/lib/yatm.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 648dc35601df1be85b015a29fff60f789820bd605e8b90e2f2b78d81fd9ec749
|
|
4
|
+
data.tar.gz: 9fad47b236af179fed6869d7813ecfa37da86fe7c8a06e53bd8abe07dde1b819
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: acd14ce8af175e496e737be3e67d91045456a8c8334d9cac9a90e7122989e0f727f40780f3ca9e641cdf128533eca3e395cb6f614188c67c9184f7953d63a571
|
|
7
|
+
data.tar.gz: da9d9e6e5ab7dcb3ec5c3bb4c0c3bded322140d509774c33b3c4ebd6257904f0d4f272d5e02d7087df4ec41fbcc30ea7748a334ebc52c7b57203ee33962fee76
|
data/lib/yatm/error.rb
CHANGED
data/lib/yatm/machine/machine.rb
CHANGED
|
@@ -1,18 +1,48 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# This is the class used to set up and use the turing machine.
|
|
4
|
+
#
|
|
5
|
+
# Use {#event} to create the various transitions. The states are automatically
|
|
6
|
+
# inferred to be all the states added through this method.
|
|
7
|
+
#
|
|
8
|
+
# Use {#initial_state} once to select the initial state, and {#final_state}
|
|
9
|
+
# however many times to mark states as final.
|
|
10
|
+
#
|
|
11
|
+
# The content of the tape can be given upon initializing the machine, through
|
|
12
|
+
# the parameter `content`, or with the method {#reset}.
|
|
13
|
+
#
|
|
14
|
+
# @example A turing machine which prints an "OX" and halts at position 0.
|
|
15
|
+
# m = YATM::Machine.new
|
|
16
|
+
# m.event nil,
|
|
17
|
+
# start: [:running, "O", :r],
|
|
18
|
+
# running: [:halt, "X", :l]
|
|
19
|
+
# m.initial_state :start
|
|
20
|
+
# m.final_state :halt
|
|
21
|
+
# m.run!
|
|
3
22
|
class YATM::Machine
|
|
4
|
-
|
|
5
|
-
|
|
23
|
+
# The tape over which values can be written and read by the machine.
|
|
24
|
+
attr_reader :tape
|
|
25
|
+
# The state machine associated with this turing machine.
|
|
26
|
+
attr_reader :state_machine
|
|
27
|
+
# @return [Array<Hash>] A record of the transitions undergone by the machine.
|
|
28
|
+
attr_reader :history
|
|
29
|
+
|
|
30
|
+
# @param position [Integer] The initial position of the machine's head.
|
|
31
|
+
# @param content [Array] The initial content of the tape, starting from position 0.
|
|
6
32
|
def initialize(position: 0, content: [nil])
|
|
7
33
|
@tape = YATM::Tape.new(content, position: position)
|
|
8
34
|
@state_machine = YATM::StateMachine.new
|
|
9
35
|
@history = []
|
|
10
36
|
end
|
|
11
37
|
|
|
38
|
+
# @param state [String, Symbol, Number] The state to be set as the starting state.
|
|
39
|
+
# @return [String, Symbol, Number] The initial state.
|
|
12
40
|
def initial_state(...); @state_machine.initial_state(...); end
|
|
13
41
|
|
|
42
|
+
# (see YATM::StateMachine#final_state)
|
|
14
43
|
def final_state(...); @state_machine.final_state(...); end
|
|
15
44
|
|
|
45
|
+
# (see YATM::StateMachine#states)
|
|
16
46
|
def states(...); @state_machine.states(...); end
|
|
17
47
|
|
|
18
48
|
def events(...); @state_machine.events(...); end
|
|
@@ -4,7 +4,12 @@ require_relative "state_machine_errors"
|
|
|
4
4
|
require_relative "event"
|
|
5
5
|
|
|
6
6
|
class YATM::StateMachine
|
|
7
|
-
|
|
7
|
+
# The current state of the state machine
|
|
8
|
+
attr_reader :current_state
|
|
9
|
+
# @return [Array<YATM::StateMachine::Event>] A list of the events that can processed by the machine
|
|
10
|
+
attr_reader :events
|
|
11
|
+
# @return [Array] A list of the final states
|
|
12
|
+
attr_reader :final_states
|
|
8
13
|
|
|
9
14
|
def initialize
|
|
10
15
|
@events = {}
|
|
@@ -15,6 +20,14 @@ class YATM::StateMachine
|
|
|
15
20
|
@current_state = @initial_state
|
|
16
21
|
end
|
|
17
22
|
|
|
23
|
+
# @return [String] A string representation of the state machine
|
|
24
|
+
#
|
|
25
|
+
# @example Example output
|
|
26
|
+
# puts state_machine.to_s
|
|
27
|
+
#
|
|
28
|
+
# | states: [:start, :A, :B, :end]
|
|
29
|
+
# | current: :start
|
|
30
|
+
# | events: [nil, 0, 1]
|
|
18
31
|
def to_s
|
|
19
32
|
<<~TO_S.chomp
|
|
20
33
|
| states: #{states}
|
|
@@ -23,33 +36,73 @@ class YATM::StateMachine
|
|
|
23
36
|
TO_S
|
|
24
37
|
end
|
|
25
38
|
|
|
39
|
+
# @return [Array] The list of all states of the state machine
|
|
26
40
|
def states
|
|
27
41
|
@events.map do |_name, event|
|
|
28
42
|
event.keys + event.map { |_, val| val[:to] }
|
|
29
43
|
end.flatten.uniq
|
|
30
44
|
end
|
|
31
45
|
|
|
32
|
-
|
|
46
|
+
# @overload initial_state(state)
|
|
47
|
+
# @param state [#to_s && #to_sym] The state to be set as the starting state
|
|
48
|
+
# @return [Object] The initial state
|
|
49
|
+
# @overload initial_state
|
|
50
|
+
# @return [Object] The initial state
|
|
51
|
+
#
|
|
52
|
+
# @see states
|
|
53
|
+
def initial_state(state = nil)
|
|
54
|
+
return @initial_state if state.nil?
|
|
55
|
+
|
|
33
56
|
@initial_state = self.class.statify(state)
|
|
34
57
|
@current_state = @initial_state
|
|
35
58
|
end
|
|
36
59
|
|
|
60
|
+
# @param states [#to_s && #to_sym] The state or array of states to be marked
|
|
61
|
+
# as final states
|
|
62
|
+
# @return [Array] The complete list of final states
|
|
37
63
|
def final_state(*states)
|
|
38
64
|
states.each do |state|
|
|
39
65
|
(@final_states << self.class.statify(state)).uniq!
|
|
40
66
|
end
|
|
67
|
+
@final_states
|
|
41
68
|
end
|
|
42
69
|
|
|
70
|
+
# @param name [Object] The name of the event.
|
|
71
|
+
#
|
|
72
|
+
# Note that this is also the value which, when read from the tape, will
|
|
73
|
+
# trigger the processing of this event.
|
|
74
|
+
# @param **transitions [Hash | Hash[, Hash...]] One or more transitions.
|
|
75
|
+
#
|
|
76
|
+
# Transitions can be of the following forms:
|
|
77
|
+
# - `state1 => [state2, value, movement]`
|
|
78
|
+
# - `state1 => [state2, value]`
|
|
79
|
+
# - `state1 => [state2]`
|
|
80
|
+
# - `state1 => state2`
|
|
81
|
+
# On all cases, the machine is going from `state1` to `state2`, writing
|
|
82
|
+
# `value` on the current position of the tape, and moving the head in the
|
|
83
|
+
# direction specified by `movement`.
|
|
84
|
+
# @return [YATM::StateMachine::Event] The event object creared
|
|
43
85
|
def event(name, **transitions)
|
|
44
86
|
@events[name] = YATM::Event.new(name, **transitions)
|
|
45
87
|
end
|
|
46
88
|
|
|
89
|
+
# @param value [Object] Tape value to be processed (trigger corresponding
|
|
90
|
+
# event) by the machine
|
|
91
|
+
# @return [Hash | nil] A representation of the transition which was triggered,
|
|
92
|
+
# or nil if none was
|
|
47
93
|
def process(value)
|
|
48
94
|
process!(value)
|
|
49
95
|
rescue StateMachineError
|
|
50
96
|
nil
|
|
51
97
|
end
|
|
52
98
|
|
|
99
|
+
# @param value [Object] Tape value to be processed (trigger corresponding
|
|
100
|
+
# event) by the machine
|
|
101
|
+
# @return [Hash] A representation of the transition which was triggered
|
|
102
|
+
# @raise [InitialStateNotSet] No initial state was set. See {initial_state}
|
|
103
|
+
# @raise [InvalidEvent] There is no event registered under the given value
|
|
104
|
+
# @raise [InvalidTransition] There is an event registered under the given
|
|
105
|
+
# value, but it contains no transitions from the machine's current state
|
|
53
106
|
def process!(value)
|
|
54
107
|
return { final: @current_state } if @final_states.include?(@current_state)
|
|
55
108
|
raise InitialStateNotSet unless @current_state
|
|
@@ -62,12 +115,24 @@ class YATM::StateMachine
|
|
|
62
115
|
transition
|
|
63
116
|
end
|
|
64
117
|
|
|
65
|
-
|
|
66
|
-
|
|
118
|
+
class << self
|
|
119
|
+
# @param state [#to_s && #to_sym] The object to be statified
|
|
120
|
+
# @return [Symbol] The object's statified form
|
|
121
|
+
# @raise [InvalidState] The object given could not be statified
|
|
122
|
+
def statify!(state)
|
|
123
|
+
raise InvalidState, state unless state.respond_to?(:to_s)
|
|
124
|
+
|
|
125
|
+
state = state.to_s
|
|
126
|
+
raise InvalidState, state unless state.respond_to?(:to_sym)
|
|
67
127
|
|
|
68
|
-
|
|
69
|
-
|
|
128
|
+
state.to_sym
|
|
129
|
+
end
|
|
70
130
|
|
|
71
|
-
state
|
|
131
|
+
# @param state [#to_s && #to_sym] The object to be statified
|
|
132
|
+
# @return [Symbol | nil] If the object could be statified, it's statified
|
|
133
|
+
# form. Nil otherwise
|
|
134
|
+
def statify(state)
|
|
135
|
+
statify!(state) rescue StateMachineError
|
|
136
|
+
end
|
|
72
137
|
end
|
|
73
138
|
end
|
data/lib/yatm/tape/tape.rb
CHANGED
data/lib/yatm/version.rb
CHANGED
data/lib/yatm.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yatm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- tiago-macedo
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-09-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |-
|
|
14
14
|
This gem provides you with the module `YATM`.
|