twisty_puzzles 0.0.12 → 0.0.16
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/twisty_puzzles/algorithm.rb +5 -2
- data/lib/twisty_puzzles/commutator.rb +15 -0
- data/lib/twisty_puzzles/parser.rb +75 -14
- data/lib/twisty_puzzles/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1477b8bdab0eb6f001734d952bb7923c96ded08d2810ad14fc6ada8cbf2976b1
|
4
|
+
data.tar.gz: 452de382df3a44d33ede47f7093e8c2204f56c26836b22e16633586e6e396ad9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8adbb4a4d7c3282e18a6c28b73184893aad54e97cf62e96945382a8305bd1638e22d5df3363bea3b0ce2e73d2162632175e836d0e231840964442fa80aab5253
|
7
|
+
data.tar.gz: 265ef1e6511c51099b41b8efeaf82b34468bb9bf9ff7e13b549d0adae1022359ec02607f667e53263feb47f076a6ee1538ee451fa831e80aadb564480449aa83
|
@@ -133,9 +133,12 @@ module TwistyPuzzles
|
|
133
133
|
|
134
134
|
def *(other)
|
135
135
|
raise TypeError unless other.is_a?(Integer)
|
136
|
-
raise ArgumentError if other.negative?
|
137
136
|
|
138
|
-
|
137
|
+
if other.negative?
|
138
|
+
inverse * -other
|
139
|
+
else
|
140
|
+
self.class.new(@moves * other)
|
141
|
+
end
|
139
142
|
end
|
140
143
|
|
141
144
|
def compiled_for_skewb
|
@@ -83,6 +83,21 @@ module TwistyPuzzles
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
+
# Slash commutator of the form A B A2 B' A.
|
87
|
+
class SlashCommutator < PureCommutator
|
88
|
+
def inverse
|
89
|
+
SlashCommutator.new(first_part.inverse, second_part)
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_s
|
93
|
+
"[#{@first_part}/#{@second_part}]"
|
94
|
+
end
|
95
|
+
|
96
|
+
def algorithm
|
97
|
+
first_part + second_part + (first_part * 2) + second_part.inverse + first_part
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
86
101
|
# Setup commutator of the form A B A'.
|
87
102
|
class SetupCommutator < Commutator
|
88
103
|
def initialize(setup, inner_commutator)
|
@@ -16,6 +16,12 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
|
|
16
16
|
OPENING_PAREN = '('
|
17
17
|
CLOSING_BRACKET = ']'
|
18
18
|
CLOSING_PAREN = ')'
|
19
|
+
SLASH = '/'
|
20
|
+
COMMA = ','
|
21
|
+
SETUP_SEPARATORS = %w[; :].freeze
|
22
|
+
PURE_SEPARATORS = [SLASH, COMMA].freeze
|
23
|
+
SEPARATORS = (SETUP_SEPARATORS + PURE_SEPARATORS).freeze
|
24
|
+
|
19
25
|
TIMES = '*'
|
20
26
|
|
21
27
|
def initialize(alg_string, move_parser)
|
@@ -77,8 +83,8 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
|
|
77
83
|
end
|
78
84
|
|
79
85
|
# Parses at least one move.
|
80
|
-
def
|
81
|
-
moves =
|
86
|
+
def parse_nonempty_moves_with_triggers
|
87
|
+
moves = parse_moves_with_triggers
|
82
88
|
complain('move') if moves.empty?
|
83
89
|
moves
|
84
90
|
end
|
@@ -89,6 +95,8 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
|
|
89
95
|
while (m = begin skip_spaces; parse_move_internal end)
|
90
96
|
moves.push(m)
|
91
97
|
end
|
98
|
+
skip_spaces
|
99
|
+
moves *= parse_multiplier if @scanner.peek(1) == TIMES
|
92
100
|
Algorithm.new(moves)
|
93
101
|
end
|
94
102
|
|
@@ -117,10 +125,26 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
|
|
117
125
|
if @scanner.peek(1) == OPENING_BRACKET
|
118
126
|
parse_commutator_internal
|
119
127
|
else
|
120
|
-
|
128
|
+
parse_commutator_no_brackets
|
121
129
|
end
|
122
130
|
end
|
123
131
|
|
132
|
+
def parse_commutator_no_brackets
|
133
|
+
setup_or_first_part_or_algorithm = parse_moves_with_triggers
|
134
|
+
skip_spaces
|
135
|
+
if @scanner.eos? || !SEPARATORS.include?(@scanner.peek(1))
|
136
|
+
return FakeCommutator.new(setup_or_first_part_or_algorithm)
|
137
|
+
end
|
138
|
+
|
139
|
+
setup_or_first_part = setup_or_first_part_or_algorithm
|
140
|
+
complain('move') if setup_or_first_part.empty?
|
141
|
+
separator = parse_separator
|
142
|
+
comm = parse_commutator_internal_after_separator(setup_or_first_part, separator)
|
143
|
+
skip_spaces
|
144
|
+
complain('end of commutator') unless @scanner.eos?
|
145
|
+
comm
|
146
|
+
end
|
147
|
+
|
124
148
|
def parse_algorithm
|
125
149
|
skip_spaces
|
126
150
|
parse_moves_with_triggers
|
@@ -131,40 +155,77 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
|
|
131
155
|
if @scanner.peek(1) == OPENING_BRACKET
|
132
156
|
parse_pure_commutator
|
133
157
|
else
|
134
|
-
|
158
|
+
parse_pure_commutator_no_brackets
|
135
159
|
end
|
136
160
|
end
|
137
161
|
|
138
162
|
def parse_pure_commutator
|
139
163
|
skip_spaces
|
140
164
|
parse_open_bracket
|
141
|
-
first_part =
|
165
|
+
first_part = parse_nonempty_moves_with_triggers
|
142
166
|
skip_spaces
|
143
|
-
|
144
|
-
second_part =
|
167
|
+
separator = parse_pure_separator
|
168
|
+
second_part = parse_nonempty_moves_with_triggers
|
145
169
|
skip_spaces
|
146
170
|
parse_close_bracket
|
147
|
-
|
171
|
+
pseudo_pure_commutator(separator, first_part, second_part)
|
172
|
+
end
|
173
|
+
|
174
|
+
def parse_pure_commutator_no_brackets
|
175
|
+
first_part_or_algorithm = parse_moves_with_triggers
|
176
|
+
skip_spaces
|
177
|
+
if @scanner.eos? || !PURE_SEPARATORS.include?(@scanner.peek(1))
|
178
|
+
return FakeCommutator.new(first_part_or_algorithm)
|
179
|
+
end
|
180
|
+
|
181
|
+
first_part = first_part_or_algorithm
|
182
|
+
complain('move') if first_part.empty?
|
183
|
+
separator = parse_pure_separator
|
184
|
+
second_part = parse_nonempty_moves_with_triggers
|
185
|
+
skip_spaces
|
186
|
+
pseudo_pure_commutator(separator, first_part, second_part)
|
187
|
+
end
|
188
|
+
|
189
|
+
def parse_pure_separator
|
190
|
+
separator = @scanner.getch
|
191
|
+
complain('middle of pure commutator') unless PURE_SEPARATORS.include?(separator)
|
192
|
+
separator
|
148
193
|
end
|
149
194
|
|
150
195
|
def parse_commutator_internal_after_separator(setup_or_first_part, separator)
|
151
|
-
if
|
196
|
+
if SETUP_SEPARATORS.include?(separator)
|
152
197
|
inner_commutator = parse_setup_commutator_inner
|
153
198
|
SetupCommutator.new(setup_or_first_part, inner_commutator)
|
154
|
-
elsif separator
|
155
|
-
second_part =
|
156
|
-
|
199
|
+
elsif PURE_SEPARATORS.include?(separator)
|
200
|
+
second_part = parse_nonempty_moves_with_triggers
|
201
|
+
pseudo_pure_commutator(separator, setup_or_first_part, second_part)
|
157
202
|
else
|
158
203
|
complain('end of setup or middle of pure commutator') unless @scanner.eos?
|
159
204
|
end
|
160
205
|
end
|
161
206
|
|
207
|
+
def pseudo_pure_commutator(separator, first_part, second_part)
|
208
|
+
if separator == COMMA
|
209
|
+
PureCommutator.new(first_part, second_part)
|
210
|
+
elsif separator == SLASH
|
211
|
+
SlashCommutator.new(first_part, second_part)
|
212
|
+
else
|
213
|
+
complain('middle of pure commutator') unless PURE_SEPARATORS.include?(separator)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def parse_separator
|
218
|
+
separator = @scanner.getch
|
219
|
+
complain('separator between commutator parts') unless SEPARATORS.include?(separator)
|
220
|
+
separator
|
221
|
+
end
|
222
|
+
|
162
223
|
def parse_commutator_internal
|
163
224
|
skip_spaces
|
164
225
|
parse_open_bracket
|
165
|
-
setup_or_first_part =
|
226
|
+
setup_or_first_part = parse_nonempty_moves_with_triggers
|
166
227
|
skip_spaces
|
167
|
-
separator =
|
228
|
+
separator = parse_separator
|
168
229
|
comm = parse_commutator_internal_after_separator(setup_or_first_part, separator)
|
169
230
|
skip_spaces
|
170
231
|
parse_close_bracket
|