Module: TwistyPuzzles::CancellationHelper
- Includes:
- CubeConstants
- Defined in:
- lib/twisty_puzzles/cancellation_helper.rb
Overview
Helper class to figure out information about the cancellation between two algs.
Constant Summary
collapse
- TRIVIAL_CENTER_TRANSFORMATION =
{ U: :U, F: :F, R: :R, L: :L, B: :B, D: :D }.freeze
- CENTER_TRANSFORMATIONS =
begin
x_transformation = { U: :B, F: :U, R: :R, L: :L, B: :D, D: :F }.freeze
y_transformation = { U: :U, F: :L, R: :F, L: :B, B: :R, D: :D }.freeze
z_transformation = { U: :R, F: :F, R: :D, L: :U, B: :B, D: :L }.freeze
{
U: create_directed_transformations(y_transformation, false),
F: create_directed_transformations(z_transformation, false),
R: create_directed_transformations(x_transformation, false),
L: create_directed_transformations(x_transformation, true),
B: create_directed_transformations(z_transformation, true),
D: create_directed_transformations(y_transformation, true)
}
end
TwistyPuzzles::CubeConstants::ALPHABET_SIZE, TwistyPuzzles::CubeConstants::CHIRALITY_FACE_SYMBOLS, TwistyPuzzles::CubeConstants::FACE_NAMES, TwistyPuzzles::CubeConstants::FACE_SYMBOLS, TwistyPuzzles::CubeConstants::OPPOSITE_FACE_SYMBOLS, TwistyPuzzles::CubeConstants::SKEWB_STICKERS
Class Method Summary
collapse
#chirality_canonical_face_symbol, #opposite_face_symbol, #valid_chirality?
#apply_permutation, #check_types, #find_only, #only, #replace_once, #rotate_out_nils, #turned_equals?
Class Method Details
.alg_plus_cancelled_move(algorithm, move, cube_size) ⇒ Object
135
136
137
138
139
140
141
142
143
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 135
def self.alg_plus_cancelled_move(algorithm, move, cube_size)
if move.is_a?(Rotation) && (tail_rotations = num_tail_rotations(algorithm)) >= 2
Algorithm.new(algorithm.moves[0...-tail_rotations]) +
cancelled_rotations(algorithm.moves[-tail_rotations..] + [move])
else
Algorithm.new(algorithm.moves[0...-1]) +
algorithm.moves[-1].join_with_cancellation(move, cube_size)
end
end
|
57
58
59
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 57
def self.apply_transformation_to!(transformation, face_state)
face_state.map! { |f| transformation[f] }
end
|
.cancel(algorithm, cube_size) ⇒ Object
Cancel this algorithm as much as possilbe
42
43
44
45
46
47
48
49
50
51
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 42
def self.cancel(algorithm, cube_size)
raise TypeError unless algorithm.is_a?(Algorithm)
CubeState.check_cube_size(cube_size)
alg = Algorithm.empty
algorithm.moves.each do |m|
alg = push_with_cancellation(alg, m, cube_size)
end
alg
end
|
.cancel_variants(algorithm) ⇒ Object
Possible variations of the algorithm where the last move has been swapped as much as allowed (e.g. D U can swap).
28
29
30
31
32
33
34
35
36
37
38
39
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 28
def self.cancel_variants(algorithm)
variants = []
algorithm.moves.each_index.reverse_each do |i|
variant = swap_to_end(algorithm, i)
break unless variant
variants.push(variant)
end
raise if variants.empty?
variants
end
|
.cancelled_rotations(rotations) ⇒ Object
120
121
122
123
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 120
def self.cancelled_rotations(rotations)
center_state = rotated_center_state(rotations)
rotation_sequences[center_state]
end
|
87
88
89
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 87
def self.center_transformation(rotation)
CENTER_TRANSFORMATIONS[rotation.axis_face.face_symbol][rotation.direction.value]
end
|
53
54
55
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 53
def self.combine_transformations(left, right)
left.dup.transform_values { |e| right[e] }.freeze
end
|
.combined_rotation_algs ⇒ Object
97
98
99
100
101
102
103
104
105
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 97
def self.combined_rotation_algs
Rotation::NON_ZERO_ROTATIONS.flat_map do |left|
second_rotations =
Rotation::NON_ZERO_ROTATIONS.reject do |e|
e.direction.double_move? || e.same_axis?(left)
end
second_rotations.map { |right| Algorithm.new([left, right]) }
end
end
|
63
64
65
66
67
68
69
70
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 63
def self.create_directed_transformations(basic_transformation, invert)
twice = combine_transformations(basic_transformation, basic_transformation)
thrice = combine_transformations(twice, basic_transformation)
non_zero_transformations = [basic_transformation, twice, thrice]
adjusted_non_zero_transformations =
invert ? non_zero_transformations.reverse : non_zero_transformations
[TRIVIAL_CENTER_TRANSFORMATION] + adjusted_non_zero_transformations
end
|
.num_tail_rotations(algorithm) ⇒ Object
125
126
127
128
129
130
131
132
133
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 125
def self.num_tail_rotations(algorithm)
num = 0
algorithm.moves.reverse_each do |e|
break unless e.is_a?(Rotation)
num += 1
end
num
end
|
.push_with_cancellation(algorithm, move, cube_size) ⇒ Object
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 145
def self.push_with_cancellation(algorithm, move, cube_size)
raise TypeError unless move.is_a?(AbstractMove)
return Algorithm.move(move) if algorithm.empty?
cancel_variants =
cancel_variants(algorithm).map do |alg|
alg_plus_cancelled_move(alg, move, cube_size)
end
cancel_variants.min_by do |alg|
[alg.move_count(cube_size, :qtm), alg.move_count(cube_size, :htm), alg.length]
end
end
|
.rotated_center_state(rotations) ⇒ Object
91
92
93
94
95
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 91
def self.rotated_center_state(rotations)
rotations.reduce(FACE_SYMBOLS.dup) do |center_state, rotation|
apply_transformation_to!(center_transformation(rotation), center_state)
end
end
|
.rotation_sequences ⇒ Object
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 107
def self.rotation_sequences
@rotation_sequences ||=
begin
trivial_rotation_algs = [Algorithm.empty]
single_rotation_algs = Rotation::NON_ZERO_ROTATIONS.map { |e| Algorithm.move(e) }
combined_rotation_algs = self.combined_rotation_algs
rotation_algs = trivial_rotation_algs + single_rotation_algs + combined_rotation_algs
rotation_algs.to_h do |alg|
[rotated_center_state(alg.moves), alg]
end.freeze
end
end
|
.swap_to_end(algorithm, index) ⇒ Object
13
14
15
16
17
18
19
20
21
22
23
24
|
# File 'lib/twisty_puzzles/cancellation_helper.rb', line 13
def self.swap_to_end(algorithm, index)
new_moves = algorithm.moves.dup
index.upto(algorithm.length - 2) do |current_index|
obstacle_index = current_index + 1
current = new_moves[current_index]
obstacle = new_moves[obstacle_index]
return nil unless current.can_swap?(obstacle)
new_moves[current_index], new_moves[obstacle_index] = current.swap(obstacle)
end
Algorithm.new(new_moves)
end
|