twisty_puzzles 0.0.12 → 0.0.16
Sign up to get free protection for your applications and to get access to all the features.
- 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
|