twisty_puzzles 0.0.11 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f6166de8734039f856869be9f20b6109c194556094bc281ae3138ada4a1ad27
4
- data.tar.gz: 6a19cc1ad482ec49831c057d944b9055f70c206882ac618892b0336e8d047e3b
3
+ metadata.gz: d5631e9c30819f3520d04ed81aa9b1ceebbee7a3da5c3b51bf2a81947f8fb3a1
4
+ data.tar.gz: fc4769b6c1ebab5d14cb64ddb3e39356a408750d1d0c7954d4929156296b9f9e
5
5
  SHA512:
6
- metadata.gz: 3ba31f44cb0df6f836d9a9b9908550cd2d6ca0ede672d4784f084b609e1249fd0e8e0f8d6cdc0b09e8faba6a462d49966c698b9d5601a4901aa0ee4eb8bc95c1
7
- data.tar.gz: 16727e63c37191c99ed1c185c851c8a541c97f110505f2c6ae5eeeabb186c11c35173d35c2441cc8c15318dd88f380656afc04690d5bb4eaa9b359b9a2725de3
6
+ metadata.gz: c941aaef4dbf2bc8d580d712d669042061c20670aadcf2ee353f353eae4eb31713de9d4791f6d8126e4427ef9e7125562e26b53c85f0a92e09bfe120e8f24f04
7
+ data.tar.gz: 5e943e567b069fd2b2e21c77fdc7a48ad3e81fb365832439cd1f402da838b5771bc7af4b2293bf635fa1b6de158ddfbea78f9981e690ce3e72a6149c6b042bd2
@@ -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
- self.class.new(@moves * other)
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)
@@ -28,7 +28,7 @@ module TwistyPuzzles
28
28
 
29
29
  # Middle coordinate for uneven numbers, the one before for even numbers
30
30
  def self.middle_or_before(cube_size)
31
- cube_size - cube_size / 2 - 1
31
+ cube_size - (cube_size / 2) - 1
32
32
  end
33
33
 
34
34
  # Middle coordinate for uneven numbers, the one after for even numbers
@@ -38,7 +38,7 @@ module TwistyPuzzles
38
38
 
39
39
  # The last coordinate that is strictly before the middle
40
40
  def self.last_before_middle(cube_size)
41
- cube_size / 2 - 1
41
+ (cube_size / 2) - 1
42
42
  end
43
43
 
44
44
  def self.canonicalize(index, cube_size)
@@ -310,7 +310,7 @@ module TwistyPuzzles
310
310
 
311
311
  def self.for_corner(corner)
312
312
  native = Native::SkewbCoordinate.for_corner(corner.face_symbols)
313
- new(Face.for_face_symbol(corner.face_symbols.first), 1 + corner.piece_index % 4, native)
313
+ new(Face.for_face_symbol(corner.face_symbols.first), 1 + (corner.piece_index % 4), native)
314
314
  end
315
315
 
316
316
  def hash
@@ -34,6 +34,14 @@ module TwistyPuzzles
34
34
 
35
35
  attr_reader :piece_index, :face_symbols
36
36
 
37
+ def self.min_parseable_face_symbols
38
+ self::FACES
39
+ end
40
+
41
+ def self.max_parseable_face_symbols
42
+ self::FACES
43
+ end
44
+
37
45
  def self.generate_parts
38
46
  valid_face_symbol_combinations =
39
47
  FACE_SYMBOLS.permutation(self::FACES).select do |p|
@@ -147,7 +155,7 @@ module TwistyPuzzles
147
155
 
148
156
  def self.parse(piece_description)
149
157
  face_symbols =
150
- piece_description.upcase.strip.split('').map do |e|
158
+ piece_description.upcase.strip.chars.map do |e|
151
159
  FACE_SYMBOLS[FACE_NAMES.index(e)]
152
160
  end
153
161
  for_face_symbols(face_symbols)
@@ -327,6 +335,14 @@ module TwistyPuzzles
327
335
  class MoveableCenter < Part
328
336
  FACES = 1
329
337
 
338
+ def self.min_parseable_face_symbols
339
+ self::CORRESPONDING_PART_CLASS::FACES
340
+ end
341
+
342
+ def self.max_parseable_face_symbols
343
+ self::CORRESPONDING_PART_CLASS::FACES
344
+ end
345
+
330
346
  def self.min_cube_size
331
347
  4
332
348
  end
@@ -467,11 +483,15 @@ module TwistyPuzzles
467
483
  false
468
484
  end
469
485
 
486
+ def self.max_parseable_face_symbols
487
+ FACES + 1
488
+ end
489
+
470
490
  def self.for_face_symbols(face_symbols)
471
491
  # One additional face symbol is usually mentioned for wings.
472
492
  raise unless face_symbols.length == FACES || face_symbols.length == FACES + 1
473
493
 
474
- if face_symbols.length == 3
494
+ if face_symbols.length == FACES + 1
475
495
  for_corner_face_symbols(face_symbols)
476
496
  else
477
497
  for_face_symbols_internal(face_symbols)
@@ -518,7 +538,7 @@ module TwistyPuzzles
518
538
  end
519
539
 
520
540
  def num_incarnations(cube_size)
521
- cube_size > 3 ? cube_size / 2 - 1 : 0
541
+ cube_size > 3 ? (cube_size / 2) - 1 : 0
522
542
  end
523
543
 
524
544
  # One index of such a piece on a on a NxN face.
@@ -617,7 +637,7 @@ module TwistyPuzzles
617
637
  ELEMENTS = generate_parts
618
638
 
619
639
  def num_incarnations(cube_size)
620
- cube_size > 3 ? cube_size / 2 - 1 : 0
640
+ cube_size > 3 ? (cube_size / 2) - 1 : 0
621
641
  end
622
642
 
623
643
  # One index of such a piece on a on a NxN face.
@@ -643,7 +663,7 @@ module TwistyPuzzles
643
663
  if cube_size.even? || cube_size <= 3
644
664
  0
645
665
  else
646
- cube_size / 2 - 1
666
+ (cube_size / 2) - 1
647
667
  end
648
668
  end
649
669
 
@@ -68,8 +68,8 @@ module TwistyPuzzles
68
68
 
69
69
  def equivalent_slice_move?(other, cube_size)
70
70
  cube_size == 3 && other.slice_index == 1 &&
71
- (@axis_face == other.axis_face && @direction == other.direction ||
72
- @axis_face == other.axis_face.opposite && @direction == other.direction.inverse)
71
+ ((@axis_face == other.axis_face && @direction == other.direction) ||
72
+ (@axis_face == other.axis_face.opposite && @direction == other.direction.inverse))
73
73
  end
74
74
  end
75
75
 
@@ -72,9 +72,9 @@ module TwistyPuzzles
72
72
  def skewb_ascii_art_line(first_color, middle_color, last_color, num_first_color)
73
73
  raise if num_first_color > SKEWB_FACE_SIZE / 2
74
74
 
75
- first_color * num_first_color +
76
- middle_color * (SKEWB_FACE_SIZE - 2 * num_first_color) +
77
- last_color * num_first_color
75
+ (first_color * num_first_color) +
76
+ (middle_color * (SKEWB_FACE_SIZE - (2 * num_first_color))) +
77
+ (last_color * num_first_color)
78
78
  end
79
79
 
80
80
  def skewb_ascii_art(center_color, corner_colors)
@@ -116,7 +116,7 @@ module TwistyPuzzles
116
116
  front_face = face_lines(cube_state, :F, 1, 3) { |c| color_character(c, color_mode) }
117
117
  right_face = face_lines(cube_state, :R, 1, 3) { |c| color_character(c, color_mode) }
118
118
  pll_line = front_face.first + right_face.first
119
- (top_face + [pll_line] * 3).join("\n")
119
+ (top_face + ([pll_line] * 3)).join("\n")
120
120
  end
121
121
 
122
122
  def cube_string(cube_state, color_mode)
@@ -150,7 +150,7 @@ module TwistyPuzzles
150
150
  end
151
151
 
152
152
  def pad_lines(lines, padding)
153
- lines.map { |line| empty_name * padding + line }
153
+ lines.map { |line| (empty_name * padding) + line }
154
154
  end
155
155
 
156
156
  def zip_concat_lines(*args)
@@ -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 parse_nonempty_moves
81
- moves = parse_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
@@ -117,10 +123,26 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
117
123
  if @scanner.peek(1) == OPENING_BRACKET
118
124
  parse_commutator_internal
119
125
  else
120
- FakeCommutator.new(parse_moves_with_triggers)
126
+ parse_commutator_no_brackets
121
127
  end
122
128
  end
123
129
 
130
+ def parse_commutator_no_brackets
131
+ setup_or_first_part_or_algorithm = parse_moves_with_triggers
132
+ skip_spaces
133
+ if @scanner.eos? || !SEPARATORS.include?(@scanner.peek(1))
134
+ return FakeCommutator.new(setup_or_first_part_or_algorithm)
135
+ end
136
+
137
+ setup_or_first_part = setup_or_first_part_or_algorithm
138
+ complain('move') if setup_or_first_part.empty?
139
+ separator = parse_separator
140
+ comm = parse_commutator_internal_after_separator(setup_or_first_part, separator)
141
+ skip_spaces
142
+ complain('end of commutator') unless @scanner.eos?
143
+ comm
144
+ end
145
+
124
146
  def parse_algorithm
125
147
  skip_spaces
126
148
  parse_moves_with_triggers
@@ -131,40 +153,77 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
131
153
  if @scanner.peek(1) == OPENING_BRACKET
132
154
  parse_pure_commutator
133
155
  else
134
- FakeCommutator.new(parse_moves_with_triggers)
156
+ parse_pure_commutator_no_brackets
135
157
  end
136
158
  end
137
159
 
138
160
  def parse_pure_commutator
139
161
  skip_spaces
140
162
  parse_open_bracket
141
- first_part = parse_nonempty_moves
163
+ first_part = parse_nonempty_moves_with_triggers
142
164
  skip_spaces
143
- complain('middle of pure commutator') unless @scanner.getch == ','
144
- second_part = parse_nonempty_moves
165
+ separator = parse_pure_separator
166
+ second_part = parse_nonempty_moves_with_triggers
145
167
  skip_spaces
146
168
  parse_close_bracket
147
- PureCommutator.new(first_part, second_part)
169
+ pseudo_pure_commutator(separator, first_part, second_part)
170
+ end
171
+
172
+ def parse_pure_commutator_no_brackets
173
+ first_part_or_algorithm = parse_moves_with_triggers
174
+ skip_spaces
175
+ if @scanner.eos? || !PURE_SEPARATORS.include?(@scanner.peek(1))
176
+ return FakeCommutator.new(first_part_or_algorithm)
177
+ end
178
+
179
+ first_part = first_part_or_algorithm
180
+ complain('move') if first_part.empty?
181
+ separator = parse_pure_separator
182
+ second_part = parse_nonempty_moves_with_triggers
183
+ skip_spaces
184
+ pseudo_pure_commutator(separator, first_part, second_part)
185
+ end
186
+
187
+ def parse_pure_separator
188
+ separator = @scanner.getch
189
+ complain('middle of pure commutator') unless PURE_SEPARATORS.include?(separator)
190
+ separator
148
191
  end
149
192
 
150
193
  def parse_commutator_internal_after_separator(setup_or_first_part, separator)
151
- if [':', ';'].include?(separator)
194
+ if SETUP_SEPARATORS.include?(separator)
152
195
  inner_commutator = parse_setup_commutator_inner
153
196
  SetupCommutator.new(setup_or_first_part, inner_commutator)
154
- elsif separator == ','
155
- second_part = parse_nonempty_moves
156
- PureCommutator.new(setup_or_first_part, second_part)
197
+ elsif PURE_SEPARATORS.include?(separator)
198
+ second_part = parse_nonempty_moves_with_triggers
199
+ pseudo_pure_commutator(separator, setup_or_first_part, second_part)
157
200
  else
158
201
  complain('end of setup or middle of pure commutator') unless @scanner.eos?
159
202
  end
160
203
  end
161
204
 
205
+ def pseudo_pure_commutator(separator, first_part, second_part)
206
+ if separator == COMMA
207
+ PureCommutator.new(first_part, second_part)
208
+ elsif separator == SLASH
209
+ SlashCommutator.new(first_part, second_part)
210
+ else
211
+ complain('middle of pure commutator') unless PURE_SEPARATORS.include?(separator)
212
+ end
213
+ end
214
+
215
+ def parse_separator
216
+ separator = @scanner.getch
217
+ complain('separator between commutator parts') unless SEPARATORS.include?(separator)
218
+ separator
219
+ end
220
+
162
221
  def parse_commutator_internal
163
222
  skip_spaces
164
223
  parse_open_bracket
165
- setup_or_first_part = parse_nonempty_moves
224
+ setup_or_first_part = parse_nonempty_moves_with_triggers
166
225
  skip_spaces
167
- separator = @scanner.getch
226
+ separator = parse_separator
168
227
  comm = parse_commutator_internal_after_separator(setup_or_first_part, separator)
169
228
  skip_spaces
170
229
  parse_close_bracket
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TwistyPuzzles
4
- VERSION = '0.0.11'
4
+ VERSION = '0.0.15'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twisty_puzzles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernhard F. Brodowsky
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-04 00:00:00.000000000 Z
11
+ date: 2021-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize