twisty_puzzles 0.0.17 → 0.0.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/twisty_puzzles/native/native.c +2 -0
- data/ext/twisty_puzzles/native/sticker_cycle.c +196 -0
- data/ext/twisty_puzzles/native/sticker_cycle.h +5 -0
- data/lib/twisty_puzzles/color_scheme.rb +11 -0
- data/lib/twisty_puzzles/cube_state.rb +4 -6
- data/lib/twisty_puzzles/part_cycle_factory.rb +2 -2
- data/lib/twisty_puzzles/rotation.rb +1 -0
- data/lib/twisty_puzzles/skewb_state.rb +0 -11
- data/lib/twisty_puzzles/sticker_cycle.rb +33 -8
- data/lib/twisty_puzzles/version.rb +1 -1
- data/lib/twisty_puzzles.rb +0 -1
- metadata +5 -4
- data/lib/twisty_puzzles/state_helper.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64f6766819367eee6807388d640a4302c3268bcf276a2b52fb4ca94ddbb0ebe2
|
4
|
+
data.tar.gz: 0d60796788d180feb10ad42fa74a6b7535092d5d4040a64375f959ac9a2023da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36cb5bdc5b75cfcb7d0a832cbff120662426ab8dd1fd1120762c3231973f27b706059f6772193ca76403859a3768d847f9ee34fb4012c52deb19226862b8b38c
|
7
|
+
data.tar.gz: 8e6a49720c6219484741a6d5d3248917c02025def3c0eacac34b0de07529b7fe42802fd5473fb782a19ca34f7bbc7319b8ef4ee705bffd135240f9d12f6eb77c
|
@@ -9,6 +9,7 @@
|
|
9
9
|
#include "skewb_coordinate.h"
|
10
10
|
#include "skewb_layer_fingerprint.h"
|
11
11
|
#include "skewb_state.h"
|
12
|
+
#include "sticker_cycle.h"
|
12
13
|
|
13
14
|
VALUE TwistyPuzzlesModule = Qnil;
|
14
15
|
VALUE NativeModule = Qnil;
|
@@ -25,4 +26,5 @@ void Init_native() {
|
|
25
26
|
init_skewb_coordinate_class_under(NativeModule);
|
26
27
|
init_skewb_layer_fingerprint_method_under(NativeModule);
|
27
28
|
init_skewb_state_class_under(NativeModule);
|
29
|
+
init_sticker_cycle_class_under(NativeModule);
|
28
30
|
}
|
@@ -0,0 +1,196 @@
|
|
1
|
+
#include "cube_state.h"
|
2
|
+
|
3
|
+
#include "cube_coordinate.h"
|
4
|
+
#include "cube_state.h"
|
5
|
+
#include "utils.h"
|
6
|
+
|
7
|
+
static ID reverse;
|
8
|
+
|
9
|
+
typedef struct {
|
10
|
+
long cube_size;
|
11
|
+
size_t length;
|
12
|
+
VALUE coordinates;
|
13
|
+
size_t* indices;
|
14
|
+
} StickerCycleData;
|
15
|
+
|
16
|
+
extern const rb_data_type_t StickerCycleData_type;
|
17
|
+
|
18
|
+
#define GetStickerCycleData(obj, data) \
|
19
|
+
do { \
|
20
|
+
TypedData_Get_Struct((obj), StickerCycleData, &StickerCycleData_type, (data)); \
|
21
|
+
} while (0)
|
22
|
+
|
23
|
+
#define GetInitializedStickerCycleData(obj, data) \
|
24
|
+
do { \
|
25
|
+
GetStickerCycleData((obj), (data)); \
|
26
|
+
if (data->indices == NULL) { \
|
27
|
+
rb_raise(rb_eArgError, "Sticker cycle isn't initialized."); \
|
28
|
+
} \
|
29
|
+
} while(0)
|
30
|
+
|
31
|
+
static VALUE StickerCycleClass = Qnil;
|
32
|
+
|
33
|
+
static void StickerCycleData_mark(void* const ptr) {
|
34
|
+
const StickerCycleData* data = ptr;
|
35
|
+
rb_gc_mark(data->coordinates);
|
36
|
+
}
|
37
|
+
|
38
|
+
static void StickerCycleData_free(void* const ptr) {
|
39
|
+
const StickerCycleData* const data = ptr;
|
40
|
+
free(data->indices);
|
41
|
+
free(ptr);
|
42
|
+
}
|
43
|
+
|
44
|
+
static size_t StickerCycleData_size(const void* const ptr) {
|
45
|
+
const StickerCycleData* const data = ptr;
|
46
|
+
return sizeof(StickerCycleData) + num_stickers(data->cube_size) * sizeof(VALUE);
|
47
|
+
}
|
48
|
+
|
49
|
+
const rb_data_type_t StickerCycleData_type = {
|
50
|
+
"TwistyPuzzles::Native::StickerCycleData",
|
51
|
+
{StickerCycleData_mark, StickerCycleData_free, StickerCycleData_size, NULL},
|
52
|
+
NULL, NULL,
|
53
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
54
|
+
};
|
55
|
+
|
56
|
+
static VALUE* malloc_indices(const size_t n) {
|
57
|
+
VALUE* const indices = malloc(n * sizeof(size_t));
|
58
|
+
if (indices == NULL) {
|
59
|
+
rb_raise(rb_eNoMemError, "Allocating sticker cycle failed.");
|
60
|
+
}
|
61
|
+
return indices;
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE StickerCycle_alloc(const VALUE klass) {
|
65
|
+
StickerCycleData* data;
|
66
|
+
const VALUE object = TypedData_Make_Struct(klass, StickerCycleData, &StickerCycleData_type, data);
|
67
|
+
data->cube_size = 0;
|
68
|
+
data->length = 0;
|
69
|
+
data->coordinates = Qnil;
|
70
|
+
data->indices = NULL;
|
71
|
+
return object;
|
72
|
+
}
|
73
|
+
|
74
|
+
static VALUE StickerCycle_initialize(const VALUE self, const VALUE cube_size, const VALUE coordinates) {
|
75
|
+
Check_Type(cube_size, T_FIXNUM);
|
76
|
+
Check_Type(coordinates, T_ARRAY);
|
77
|
+
const long checked_cube_size = FIX2INT(cube_size);
|
78
|
+
check_cube_size(checked_cube_size);
|
79
|
+
const size_t n = RARRAY_LEN(coordinates);
|
80
|
+
StickerCycleData* data;
|
81
|
+
GetStickerCycleData(self, data);
|
82
|
+
data->cube_size = checked_cube_size;
|
83
|
+
data->length = n;
|
84
|
+
data->coordinates = coordinates;
|
85
|
+
data->indices = malloc_indices(data->length);
|
86
|
+
for (size_t i = 0; i < n; ++i) {
|
87
|
+
const VALUE coordinate = rb_ary_entry(coordinates, i);
|
88
|
+
data->indices[i] = CubeCoordinate_sticker_index(coordinate, checked_cube_size);
|
89
|
+
}
|
90
|
+
return self;
|
91
|
+
}
|
92
|
+
|
93
|
+
static VALUE StickerCycle_apply_to(const VALUE self, const VALUE cube_state) {
|
94
|
+
const StickerCycleData* sticker_cycle_data;
|
95
|
+
GetInitializedStickerCycleData(self, sticker_cycle_data);
|
96
|
+
|
97
|
+
const CubeStateData* cube_state_data;
|
98
|
+
GetInitializedCubeStateData(cube_state, cube_state_data);
|
99
|
+
|
100
|
+
if (cube_state_data->cube_size != sticker_cycle_data->cube_size) {
|
101
|
+
rb_raise(rb_eArgError, "Cube size of sticker cycle must equal cube size of cube state. Got %ld vs %ld.", sticker_cycle_data->cube_size, cube_state_data->cube_size);
|
102
|
+
}
|
103
|
+
if (sticker_cycle_data->length >= 2) {
|
104
|
+
apply_sticker_cycle(cube_state_data->stickers, sticker_cycle_data->indices, sticker_cycle_data->length, false);
|
105
|
+
}
|
106
|
+
return Qnil;
|
107
|
+
}
|
108
|
+
|
109
|
+
static VALUE StickerCycle_hash(const VALUE self) {
|
110
|
+
const StickerCycleData* data;
|
111
|
+
GetInitializedStickerCycleData(self, data);
|
112
|
+
|
113
|
+
st_index_t hash = rb_hash_start((st_index_t)StickerCycle_hash);
|
114
|
+
hash = rb_hash_uint(hash, data->length);
|
115
|
+
hash = rb_hash_uint(hash, data->cube_size);
|
116
|
+
const size_t n = data->length;
|
117
|
+
for (size_t i = 0; i < n; ++i) {
|
118
|
+
hash = rb_hash_uint(hash, data->indices[i]);
|
119
|
+
}
|
120
|
+
return ST2FIX(rb_hash_end(hash));
|
121
|
+
}
|
122
|
+
|
123
|
+
static VALUE StickerCycle_eql(const VALUE self, const VALUE other) {
|
124
|
+
if (self == other) {
|
125
|
+
return Qtrue;
|
126
|
+
}
|
127
|
+
if (rb_obj_class(self) != rb_obj_class(other)) {
|
128
|
+
return Qfalse;
|
129
|
+
}
|
130
|
+
const StickerCycleData* self_data;
|
131
|
+
GetInitializedStickerCycleData(self, self_data);
|
132
|
+
const StickerCycleData* other_data;
|
133
|
+
GetInitializedStickerCycleData(other, other_data);
|
134
|
+
if (self_data->cube_size != other_data->cube_size) {
|
135
|
+
return Qfalse;
|
136
|
+
}
|
137
|
+
if (self_data->length != other_data->length) {
|
138
|
+
return Qfalse;
|
139
|
+
}
|
140
|
+
const size_t n = self_data->length;
|
141
|
+
for (size_t i = 0; i < n; ++i) {
|
142
|
+
if (self_data->indices[i] != other_data->indices[i]) {
|
143
|
+
return Qfalse;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
return Qtrue;
|
147
|
+
}
|
148
|
+
|
149
|
+
static VALUE StickerCycle_cube_size(const VALUE self) {
|
150
|
+
const StickerCycleData* data;
|
151
|
+
GetInitializedStickerCycleData(self, data);
|
152
|
+
return ST2FIX(data->cube_size);
|
153
|
+
}
|
154
|
+
|
155
|
+
static VALUE StickerCycle_length(const VALUE self) {
|
156
|
+
const StickerCycleData* data;
|
157
|
+
GetInitializedStickerCycleData(self, data);
|
158
|
+
return ST2FIX(data->length);
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE StickerCycle_coordinates(const VALUE self) {
|
162
|
+
const StickerCycleData* data;
|
163
|
+
GetInitializedStickerCycleData(self, data);
|
164
|
+
return data->coordinates;
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE StickerCycle_inverse(const VALUE self) {
|
168
|
+
const StickerCycleData* data;
|
169
|
+
GetInitializedStickerCycleData(self, data);
|
170
|
+
const long n = data->length;
|
171
|
+
StickerCycleData* inverse_data;
|
172
|
+
const VALUE inverse = TypedData_Make_Struct(rb_obj_class(self), StickerCycleData, &StickerCycleData_type, inverse_data);
|
173
|
+
inverse_data->cube_size = data->cube_size;
|
174
|
+
inverse_data->length = n;
|
175
|
+
inverse_data->indices = malloc_indices(n);
|
176
|
+
inverse_data->coordinates = rb_funcall(data->coordinates, reverse, 0);
|
177
|
+
for (int i = 0; i < n; ++i) {
|
178
|
+
inverse_data->indices[i] = data->indices[n - 1 - i];
|
179
|
+
}
|
180
|
+
return inverse;
|
181
|
+
}
|
182
|
+
|
183
|
+
void init_sticker_cycle_class_under(const VALUE module) {
|
184
|
+
reverse = rb_intern("reverse");
|
185
|
+
StickerCycleClass = rb_define_class_under(module, "StickerCycle", rb_cObject);
|
186
|
+
rb_define_alloc_func(StickerCycleClass, StickerCycle_alloc);
|
187
|
+
rb_define_method(StickerCycleClass, "initialize", StickerCycle_initialize, 2);
|
188
|
+
rb_define_method(StickerCycleClass, "apply_to", StickerCycle_apply_to, 1);
|
189
|
+
rb_define_method(StickerCycleClass, "hash", StickerCycle_hash, 0);
|
190
|
+
rb_define_method(StickerCycleClass, "eql?", StickerCycle_eql, 1);
|
191
|
+
rb_define_alias(StickerCycleClass, "==", "eql?");
|
192
|
+
rb_define_method(StickerCycleClass, "cube_size", StickerCycle_cube_size, 0);
|
193
|
+
rb_define_method(StickerCycleClass, "length", StickerCycle_length, 0);
|
194
|
+
rb_define_method(StickerCycleClass, "coordinates", StickerCycle_coordinates, 0);
|
195
|
+
rb_define_method(StickerCycleClass, "inverse", StickerCycle_inverse, 0);
|
196
|
+
}
|
@@ -28,6 +28,17 @@ module TwistyPuzzles
|
|
28
28
|
@colors_to_face_symbols = face_symbols_to_colors.invert
|
29
29
|
end
|
30
30
|
|
31
|
+
|
32
|
+
def eql?(other)
|
33
|
+
self.class.equal?(other.class) && colors == other.colors
|
34
|
+
end
|
35
|
+
|
36
|
+
alias == eql?
|
37
|
+
|
38
|
+
def hash
|
39
|
+
@hash ||= ([self.class] + colors).hash
|
40
|
+
end
|
41
|
+
|
31
42
|
def color(face_symbol)
|
32
43
|
@face_symbols_to_colors[face_symbol]
|
33
44
|
end
|
@@ -4,7 +4,6 @@ require 'twisty_puzzles/cube'
|
|
4
4
|
require 'twisty_puzzles/cube_constants'
|
5
5
|
require 'twisty_puzzles/coordinate'
|
6
6
|
require 'twisty_puzzles/cube_print_helper'
|
7
|
-
require 'twisty_puzzles/state_helper'
|
8
7
|
require 'twisty_puzzles/utils/array_helper'
|
9
8
|
require 'twisty_puzzles/native'
|
10
9
|
|
@@ -13,7 +12,6 @@ module TwistyPuzzles
|
|
13
12
|
class CubeState
|
14
13
|
include Utils::ArrayHelper
|
15
14
|
include CubePrintHelper
|
16
|
-
include StateHelper
|
17
15
|
include CubeConstants
|
18
16
|
|
19
17
|
def self.check_cube_size(cube_size)
|
@@ -75,6 +73,10 @@ module TwistyPuzzles
|
|
75
73
|
|
76
74
|
alias == eql?
|
77
75
|
|
76
|
+
def hash
|
77
|
+
@hash ||= [self.class, @native].hash
|
78
|
+
end
|
79
|
+
|
78
80
|
def rotation_algorithms
|
79
81
|
Rotation::ALL_ROTATIONS.combination(2).reject do |r0, r1|
|
80
82
|
r0.inverse == r1
|
@@ -85,10 +87,6 @@ module TwistyPuzzles
|
|
85
87
|
rotation_algorithms.any? { |r| r.apply_temporarily_to(self) { |state| state == other } }
|
86
88
|
end
|
87
89
|
|
88
|
-
def hash
|
89
|
-
@hash ||= [self.class, @native].hash
|
90
|
-
end
|
91
|
-
|
92
90
|
# TODO: Get rid of this backwards compatibility artifact
|
93
91
|
def sticker_array(face)
|
94
92
|
raise TypeError unless face.is_a?(Face)
|
@@ -28,7 +28,7 @@ module TwistyPuzzles
|
|
28
28
|
raise TypeError, 'Twists are only supported for edges and corners.'
|
29
29
|
end
|
30
30
|
|
31
|
-
cycles = parts.map { |p| StickerCycle.
|
31
|
+
cycles = parts.map { |p| StickerCycle.from_coordinates(@cube_size, coordinates(p)) }
|
32
32
|
StickerCycles.new(@cube_size, cycles)
|
33
33
|
end
|
34
34
|
|
@@ -49,7 +49,7 @@ module TwistyPuzzles
|
|
49
49
|
check_types(parts, Part)
|
50
50
|
check_type_consistency(parts)
|
51
51
|
part_coordinates = parts.map { |p| coordinates(p) }
|
52
|
-
cycles = part_coordinates.transpose.map { |c| StickerCycle.
|
52
|
+
cycles = part_coordinates.transpose.map { |c| StickerCycle.from_coordinates(@cube_size, c) }
|
53
53
|
StickerCycles.new(@cube_size, cycles)
|
54
54
|
end
|
55
55
|
end
|
@@ -3,14 +3,12 @@
|
|
3
3
|
require 'twisty_puzzles/coordinate'
|
4
4
|
require 'twisty_puzzles/cube'
|
5
5
|
require 'twisty_puzzles/cube_print_helper'
|
6
|
-
require 'twisty_puzzles/state_helper'
|
7
6
|
require 'twisty_puzzles/cube_constants'
|
8
7
|
|
9
8
|
module TwistyPuzzles
|
10
9
|
# Represents the state (i.e. the sticker positions) of a Skewb.
|
11
10
|
class SkewbState
|
12
11
|
include CubePrintHelper
|
13
|
-
include StateHelper
|
14
12
|
include CubeConstants
|
15
13
|
# Pairs of coordinate pairs that should match in case of solved layers.
|
16
14
|
MATCHING_CORNERS =
|
@@ -151,14 +149,5 @@ module TwistyPuzzles
|
|
151
149
|
|
152
150
|
layer_check_neighbors(face).map { |c| self[c] }.uniq.length == 1
|
153
151
|
end
|
154
|
-
|
155
|
-
def rotate_face(face, direction)
|
156
|
-
neighbors = face.neighbors
|
157
|
-
inverse_order_face = face.coordinate_index_close_to(neighbors[0]) <
|
158
|
-
face.coordinate_index_close_to(neighbors[1])
|
159
|
-
direction = direction.inverse if inverse_order_face
|
160
|
-
cycle = SkewbCoordinate.corners_on_face(face)
|
161
|
-
apply_4sticker_cycle(cycle, direction)
|
162
|
-
end
|
163
152
|
end
|
164
153
|
end
|
@@ -10,22 +10,47 @@ module TwistyPuzzles
|
|
10
10
|
class StickerCycle
|
11
11
|
include ReversibleApplyable
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
13
|
+
def self.from_coordinates(cube_size, coordinates)
|
14
|
+
CubeState.check_cube_size(cube_size)
|
15
|
+
raise TypeError unless coordinates.all?(Coordinate)
|
16
|
+
|
17
|
+
new(Native::StickerCycle.new(cube_size, coordinates.map(&:native)))
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(native)
|
21
|
+
raise TypeError unless native.is_a?(Native::StickerCycle)
|
22
|
+
|
23
|
+
@native = native
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :native
|
27
|
+
|
28
|
+
def eql?(other)
|
29
|
+
self.class.equal?(other.class) && @native == other.native
|
16
30
|
end
|
17
31
|
|
18
|
-
|
32
|
+
alias == eql?
|
33
|
+
|
34
|
+
def hash
|
35
|
+
@hash ||= [self.class, @native].hash
|
36
|
+
end
|
37
|
+
|
38
|
+
def cube_size
|
39
|
+
@native.cube_size
|
40
|
+
end
|
41
|
+
|
42
|
+
def length
|
43
|
+
@native.length
|
44
|
+
end
|
19
45
|
|
20
46
|
def apply_to(cube_state)
|
21
47
|
raise TypeError unless cube_state.is_a?(CubeState)
|
22
|
-
raise ArgumentError unless cube_state.n == @cube_size
|
23
48
|
|
24
|
-
cube_state.
|
49
|
+
@native.apply_to(cube_state.native)
|
25
50
|
end
|
26
51
|
|
27
52
|
def inverse
|
28
|
-
StickerCycle.new(@
|
53
|
+
StickerCycle.new(@native.inverse)
|
29
54
|
end
|
30
55
|
end
|
31
56
|
|
@@ -38,7 +63,7 @@ module TwistyPuzzles
|
|
38
63
|
sticker_cycles.each do |c|
|
39
64
|
raise TypeError unless c.is_a?(StickerCycle)
|
40
65
|
|
41
|
-
c.
|
66
|
+
c.native.coordinates.each do |s|
|
42
67
|
raise ArgumentError unless affected_set.add?(s)
|
43
68
|
end
|
44
69
|
end
|
data/lib/twisty_puzzles.rb
CHANGED
@@ -33,7 +33,6 @@ require 'twisty_puzzles/skewb_move'
|
|
33
33
|
require 'twisty_puzzles/skewb_move_parser'
|
34
34
|
require 'twisty_puzzles/skewb_notation'
|
35
35
|
require 'twisty_puzzles/skewb_state'
|
36
|
-
require 'twisty_puzzles/state_helper'
|
37
36
|
require 'twisty_puzzles/sticker_cycle'
|
38
37
|
require 'twisty_puzzles/twisty_puzzles_error'
|
39
38
|
require 'twisty_puzzles/version'
|
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.
|
4
|
+
version: 0.0.19
|
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-11-
|
11
|
+
date: 2021-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -196,6 +196,8 @@ files:
|
|
196
196
|
- ext/twisty_puzzles/native/skewb_layer_fingerprint.h
|
197
197
|
- ext/twisty_puzzles/native/skewb_state.c
|
198
198
|
- ext/twisty_puzzles/native/skewb_state.h
|
199
|
+
- ext/twisty_puzzles/native/sticker_cycle.c
|
200
|
+
- ext/twisty_puzzles/native/sticker_cycle.h
|
199
201
|
- ext/twisty_puzzles/native/utils.c
|
200
202
|
- ext/twisty_puzzles/native/utils.h
|
201
203
|
- lib/twisty_puzzles.rb
|
@@ -231,7 +233,6 @@ files:
|
|
231
233
|
- lib/twisty_puzzles/skewb_move_parser.rb
|
232
234
|
- lib/twisty_puzzles/skewb_notation.rb
|
233
235
|
- lib/twisty_puzzles/skewb_state.rb
|
234
|
-
- lib/twisty_puzzles/state_helper.rb
|
235
236
|
- lib/twisty_puzzles/sticker_cycle.rb
|
236
237
|
- lib/twisty_puzzles/twisty_puzzles_error.rb
|
237
238
|
- lib/twisty_puzzles/utils.rb
|
@@ -260,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
260
261
|
- !ruby/object:Gem::Version
|
261
262
|
version: '0'
|
262
263
|
requirements: []
|
263
|
-
rubygems_version: 3.2.
|
264
|
+
rubygems_version: 3.2.22
|
264
265
|
signing_key:
|
265
266
|
specification_version: 4
|
266
267
|
summary: Gem for my cube_trainer rails app. Some things are better left in a separate
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'twisty_puzzles/abstract_direction'
|
4
|
-
|
5
|
-
module TwistyPuzzles
|
6
|
-
# Common utilities for different puzzle states.
|
7
|
-
# TODO: Remove
|
8
|
-
module StateHelper
|
9
|
-
def apply_sticker_cycle(cycle)
|
10
|
-
last_sticker = self[cycle[-1]]
|
11
|
-
(cycle.length - 1).downto(1) do |i|
|
12
|
-
self[cycle[i]] = self[cycle[i - 1]]
|
13
|
-
end
|
14
|
-
self[cycle[0]] = last_sticker
|
15
|
-
end
|
16
|
-
|
17
|
-
def apply_4sticker_cycle(cycle, direction)
|
18
|
-
raise ArgumentError unless cycle.length == 4
|
19
|
-
raise TypeError unless direction.is_a?(AbstractDirection)
|
20
|
-
|
21
|
-
if direction.double_move?
|
22
|
-
apply_sticker_cycle([cycle[0], cycle[2]])
|
23
|
-
apply_sticker_cycle([cycle[1], cycle[3]])
|
24
|
-
else
|
25
|
-
# Note that we cannot do reverse! because the values are cached.
|
26
|
-
actual_cycle = direction.value == 3 ? cycle.reverse : cycle
|
27
|
-
apply_sticker_cycle(actual_cycle)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|