twisty_puzzles 0.0.7 → 0.0.8
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/cube_algorithm.c +10 -18
- data/ext/twisty_puzzles/native/cube_average.c +2 -2
- data/ext/twisty_puzzles/native/cube_coordinate.c +16 -15
- data/ext/twisty_puzzles/native/cube_coordinate.h +7 -7
- data/ext/twisty_puzzles/native/cube_state.c +23 -33
- data/ext/twisty_puzzles/native/cube_state.h +2 -2
- data/ext/twisty_puzzles/native/face_symbols.h +2 -2
- data/ext/twisty_puzzles/native/skewb_algorithm.c +3 -12
- data/ext/twisty_puzzles/native/skewb_coordinate.c +0 -11
- data/ext/twisty_puzzles/native/skewb_layer_fingerprint.c +3 -2
- data/ext/twisty_puzzles/native/skewb_state.c +0 -2
- data/ext/twisty_puzzles/native/utils.c +7 -1
- data/ext/twisty_puzzles/native/utils.h +2 -0
- 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: be6ba7974d92dd52a2b5b6307c38aae5695147003ed5f41c4fc36862ada74fb9
|
4
|
+
data.tar.gz: 8a6e4e82d8a76432c4a4e526fa664886aa2da41e4018ff260894cb4f3f96daec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 478cc39f6e3e15184cac71f77680165735638a20f4fa431a311f544e0c0a44ea344d12d043fa318e6bbfd25dc76af7c2baef90ae286612c4d8cf18921c371520
|
7
|
+
data.tar.gz: d2b1dbefc310a59df6fe927951d8e1fdec5d553f6a4ce4d54c6caec51f0d7a69e688fedac652f32153ebbeb71459fd2f2e042d65f1febd45169c8f8a5f6a8cb6
|
@@ -18,12 +18,12 @@ typedef struct {
|
|
18
18
|
CubeMoveType type;
|
19
19
|
face_index_t axis_face_index;
|
20
20
|
direction_t direction;
|
21
|
-
|
21
|
+
long slice_index;
|
22
22
|
} CubeMove;
|
23
23
|
|
24
24
|
typedef struct {
|
25
25
|
size_t size;
|
26
|
-
|
26
|
+
long cube_size;
|
27
27
|
CubeMove* moves;
|
28
28
|
} CubeAlgorithmData;
|
29
29
|
|
@@ -45,15 +45,6 @@ const rb_data_type_t CubeAlgorithmData_type = {
|
|
45
45
|
RUBY_TYPED_FREE_IMMEDIATELY
|
46
46
|
};
|
47
47
|
|
48
|
-
static void check_moves(const CubeAlgorithmData* const data, const char* const name) {
|
49
|
-
for (size_t i = 0; i < data->size; ++i) {
|
50
|
-
const CubeMoveType type = data->moves[i].type;
|
51
|
-
if (type != SLICE && type != FACE) {
|
52
|
-
rb_raise(rb_eRuntimeError, "invalid move type %d in %s", type, name);
|
53
|
-
}
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
48
|
static CubeMove* malloc_moves(const size_t n) {
|
58
49
|
CubeMove* const moves = malloc(n * sizeof(CubeMove));
|
59
50
|
if (moves == NULL) {
|
@@ -96,7 +87,7 @@ static CubeMoveType extract_move_type(const VALUE move_symbol) {
|
|
96
87
|
}
|
97
88
|
}
|
98
89
|
|
99
|
-
static
|
90
|
+
static long components_for_move_type(const CubeMoveType type) {
|
100
91
|
switch (type) {
|
101
92
|
case SLICE:
|
102
93
|
return 4;
|
@@ -112,24 +103,25 @@ static VALUE CubeAlgorithm_initialize(const VALUE self, const VALUE cube_size, c
|
|
112
103
|
CubeAlgorithmData* data;
|
113
104
|
GetCubeAlgorithmData(self, data);
|
114
105
|
data->size = RARRAY_LEN(moves);
|
115
|
-
data->cube_size =
|
106
|
+
data->cube_size = FIX2INT(cube_size);
|
107
|
+
check_cube_size(data->cube_size);
|
116
108
|
data->moves = malloc_moves(data->size);
|
117
|
-
for (
|
109
|
+
for (long i = 0; i < RARRAY_LEN(moves); ++i) {
|
118
110
|
const VALUE move = rb_ary_entry(moves, i);
|
119
111
|
if (RARRAY_LEN(move) < 1) {
|
120
112
|
rb_raise(rb_eArgError, "Moves cannot be empty.");
|
121
113
|
}
|
122
114
|
const CubeMoveType type = extract_move_type(rb_ary_entry(move, 0));
|
123
|
-
const
|
115
|
+
const long num_components = components_for_move_type(type);
|
124
116
|
if (RARRAY_LEN(move) != num_components) {
|
125
117
|
rb_raise(rb_eArgError, "Moves with the given type need to have %ld elements. Got %ld.", num_components, RARRAY_LEN(move));
|
126
118
|
}
|
127
119
|
data->moves[i].type = type;
|
128
120
|
data->moves[i].axis_face_index = face_index(rb_ary_entry(move, 1));
|
129
|
-
data->moves[i].direction =
|
121
|
+
data->moves[i].direction = FIX2INT(rb_ary_entry(move, 2));
|
130
122
|
if (type == SLICE) {
|
131
|
-
const
|
132
|
-
if (slice_index >= data->cube_size) {
|
123
|
+
const long slice_index = FIX2INT(rb_ary_entry(move, 3));
|
124
|
+
if (slice_index < 0 || slice_index >= data->cube_size) {
|
133
125
|
rb_raise(rb_eArgError, "Invalid slice index %ld for cube size %ld.", slice_index, data->cube_size);
|
134
126
|
}
|
135
127
|
data->moves[i].slice_index = slice_index;
|
@@ -59,7 +59,7 @@ static VALUE CubeAverage_alloc(const VALUE klass) {
|
|
59
59
|
|
60
60
|
static VALUE CubeAverage_initialize(const VALUE self, const VALUE capacity, const VALUE initial_average) {
|
61
61
|
Check_Type(capacity, T_FIXNUM);
|
62
|
-
const
|
62
|
+
const long n = FIX2INT(capacity);
|
63
63
|
if (n < 3) {
|
64
64
|
rb_raise(rb_eArgError, "The number of elements for a cube average has to be at least 3. Got %ld.", n);
|
65
65
|
}
|
@@ -147,7 +147,7 @@ static VALUE CubeAverage_push_all(const VALUE self, const VALUE new_values) {
|
|
147
147
|
const size_t insert_index = data->insert_index;
|
148
148
|
const size_t capacity = data->capacity;
|
149
149
|
const size_t start = num_values > capacity ? num_values - capacity : 0;
|
150
|
-
for (
|
150
|
+
for (long i = start; i < RARRAY_LEN(new_values); ++i) {
|
151
151
|
const VALUE new_value = rb_ary_entry(new_values, i);
|
152
152
|
data->values[(insert_index + i) % capacity] = NUM2DBL(new_value);
|
153
153
|
}
|
@@ -5,7 +5,7 @@
|
|
5
5
|
static VALUE CubeCoordinateClass = Qnil;
|
6
6
|
|
7
7
|
typedef struct {
|
8
|
-
|
8
|
+
long cube_size;
|
9
9
|
face_index_t on_face_index;
|
10
10
|
Point point;
|
11
11
|
} CubeCoordinateData;
|
@@ -26,15 +26,15 @@ const rb_data_type_t CubeCoordinateData_type = {
|
|
26
26
|
TypedData_Get_Struct((obj), CubeCoordinateData, &CubeCoordinateData_type, (data)); \
|
27
27
|
} while (0)
|
28
28
|
|
29
|
-
size_t num_stickers(const
|
29
|
+
size_t num_stickers(const long cube_size) {
|
30
30
|
return cube_faces * cube_size * cube_size;
|
31
31
|
}
|
32
32
|
|
33
|
-
size_t sticker_index(const
|
33
|
+
size_t sticker_index(const long cube_size, const face_index_t on_face_index, const Point point) {
|
34
34
|
return on_face_index * cube_size * cube_size + point.y * cube_size + point.x;
|
35
35
|
}
|
36
36
|
|
37
|
-
size_t CubeCoordinate_sticker_index(const VALUE self, const
|
37
|
+
size_t CubeCoordinate_sticker_index(const VALUE self, const long cube_size) {
|
38
38
|
CubeCoordinateData* data;
|
39
39
|
GetCubeCoordinateData(self, data);
|
40
40
|
if (data->cube_size != cube_size) {
|
@@ -53,11 +53,11 @@ static VALUE CubeCoordinate_alloc(const VALUE klass) {
|
|
53
53
|
return object;
|
54
54
|
}
|
55
55
|
|
56
|
-
static
|
56
|
+
static long inverted_index(const long cube_size, const long index) {
|
57
57
|
return cube_size - 1 - index;
|
58
58
|
}
|
59
59
|
|
60
|
-
|
60
|
+
long transform_index(const face_index_t index_base_face_index, const long cube_size, const long index) {
|
61
61
|
if (index_base_face_index == axis_index(index_base_face_index)) {
|
62
62
|
return index;
|
63
63
|
} else {
|
@@ -86,11 +86,11 @@ void check_base_face_indices(const face_index_t on_face_index,
|
|
86
86
|
Point point_on_face(const face_index_t face_index,
|
87
87
|
const face_index_t x_base_face_index,
|
88
88
|
const face_index_t y_base_face_index,
|
89
|
-
const
|
90
|
-
const
|
91
|
-
const
|
92
|
-
const
|
93
|
-
const
|
89
|
+
const long cube_size,
|
90
|
+
const long untransformed_x,
|
91
|
+
const long untransformed_y) {
|
92
|
+
const long transformed_x = transform_index(x_base_face_index, cube_size, untransformed_x);
|
93
|
+
const long transformed_y = transform_index(y_base_face_index, cube_size, untransformed_y);
|
94
94
|
Point point;
|
95
95
|
if (switch_axes(x_base_face_index, y_base_face_index)) {
|
96
96
|
point.x = transformed_y;
|
@@ -102,7 +102,7 @@ Point point_on_face(const face_index_t face_index,
|
|
102
102
|
return point;
|
103
103
|
}
|
104
104
|
|
105
|
-
static void check_cube_index(const
|
105
|
+
static void check_cube_index(const long cube_size, const long index) {
|
106
106
|
if (index < 0 || index >= cube_size) {
|
107
107
|
rb_raise(rb_eArgError, "Invalid value %ld for x with cube size %ld.", index, cube_size);
|
108
108
|
}
|
@@ -121,14 +121,15 @@ static VALUE CubeCoordinate_initialize(const VALUE self,
|
|
121
121
|
Check_Type(y_base_face_symbol, T_SYMBOL);
|
122
122
|
Check_Type(x_num, T_FIXNUM);
|
123
123
|
Check_Type(y_num, T_FIXNUM);
|
124
|
-
const
|
124
|
+
const long n = FIX2INT(cube_size);
|
125
|
+
check_cube_size(n);
|
125
126
|
const face_index_t on_face_index = face_index(face_symbol);
|
126
127
|
const face_index_t x_base_face_index = face_index(x_base_face_symbol);
|
127
128
|
const face_index_t y_base_face_index = face_index(y_base_face_symbol);
|
128
129
|
check_base_face_indices(on_face_index, x_base_face_index, y_base_face_index);
|
129
|
-
const
|
130
|
+
const long untransformed_x = FIX2INT(x_num);
|
130
131
|
check_cube_index(n, untransformed_x);
|
131
|
-
const
|
132
|
+
const long untransformed_y = FIX2INT(y_num);
|
132
133
|
check_cube_index(n, untransformed_y);
|
133
134
|
const Point point = point_on_face(on_face_index, x_base_face_index, y_base_face_index, n, untransformed_x, untransformed_y);
|
134
135
|
CubeCoordinateData* data;
|
@@ -5,16 +5,16 @@
|
|
5
5
|
#include "face_symbols.h"
|
6
6
|
#include "utils.h"
|
7
7
|
|
8
|
-
size_t num_stickers(
|
8
|
+
size_t num_stickers(long cube_size);
|
9
9
|
|
10
10
|
typedef struct {
|
11
11
|
size_t x;
|
12
12
|
size_t y;
|
13
13
|
} Point;
|
14
14
|
|
15
|
-
size_t sticker_index(
|
15
|
+
size_t sticker_index(long cube_size, face_index_t on_face_index, Point point);
|
16
16
|
|
17
|
-
|
17
|
+
long transform_index(face_index_t index_base_face_index, long cube_size, long index);
|
18
18
|
|
19
19
|
bool switch_axes(face_index_t x_base_face_index, face_index_t y_base_face_index);
|
20
20
|
|
@@ -25,10 +25,10 @@ void check_base_face_indices(face_index_t on_face_index,
|
|
25
25
|
Point point_on_face(face_index_t on_face_index,
|
26
26
|
face_index_t x_base_face_index,
|
27
27
|
face_index_t y_base_face_index,
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
long cube_size,
|
29
|
+
long untransformed_x,
|
30
|
+
long untransformed_y);
|
31
31
|
|
32
|
-
size_t CubeCoordinate_sticker_index(VALUE self,
|
32
|
+
size_t CubeCoordinate_sticker_index(VALUE self, long cube_size);
|
33
33
|
|
34
34
|
void init_cube_coordinate_class_under(VALUE module);
|
@@ -12,7 +12,7 @@ static VALUE CubeStateClass = Qnil;
|
|
12
12
|
|
13
13
|
static void CubeStateData_mark(void* const ptr) {
|
14
14
|
const CubeStateData* data = ptr;
|
15
|
-
const
|
15
|
+
const long n = data->cube_size;
|
16
16
|
for (size_t i = 0; i < num_stickers(n); ++i) {
|
17
17
|
rb_gc_mark(data->stickers[i]);
|
18
18
|
}
|
@@ -52,19 +52,10 @@ static VALUE CubeState_alloc(const VALUE klass) {
|
|
52
52
|
return object;
|
53
53
|
}
|
54
54
|
|
55
|
-
static size_t extract_index_base_face_index(const VALUE face_hash, const VALUE key) {
|
56
|
-
const VALUE index_base_face_symbol = rb_hash_aref(face_hash, key);
|
57
|
-
if (index_base_face_symbol == Qnil) {
|
58
|
-
rb_raise(rb_eTypeError, "Cube faces must have keys called :{x,y}_base_face_symbol that describes which face an x or y value of 0 is close to.");
|
59
|
-
}
|
60
|
-
Check_Type(index_base_face_symbol, T_SYMBOL);
|
61
|
-
return face_index(index_base_face_symbol);
|
62
|
-
}
|
63
|
-
|
64
55
|
static int CubeState_replace_face(const VALUE key, const VALUE value, const VALUE self) {
|
65
56
|
const CubeStateData* data;
|
66
57
|
GetInitializedCubeStateData(self, data);
|
67
|
-
const
|
58
|
+
const long n = data->cube_size;
|
68
59
|
Check_Type(value, T_HASH);
|
69
60
|
if (RHASH_SIZE(value) != 3) {
|
70
61
|
rb_raise(rb_eTypeError, "Cube faces must have 3 entries, got %ld.", RHASH_SIZE(value));
|
@@ -75,19 +66,17 @@ static int CubeState_replace_face(const VALUE key, const VALUE value, const VALU
|
|
75
66
|
if (stickers == Qnil) {
|
76
67
|
rb_raise(rb_eTypeError, "Cube faces must have a key called :stickers that contains the stickers on that face.");
|
77
68
|
}
|
78
|
-
const face_index_t x_base_face_index = extract_index_base_face_index(value, ID2SYM(x_base_face_symbol_id));
|
79
|
-
const face_index_t y_base_face_index = extract_index_base_face_index(value, ID2SYM(y_base_face_symbol_id));
|
80
69
|
Check_Type(stickers, T_ARRAY);
|
81
70
|
if (RARRAY_LEN(stickers) != n) {
|
82
71
|
rb_raise(rb_eArgError, "All faces of a %ldx%ld cube must have %ld rows. Got %ld rows.", n, n, n, RARRAY_LEN(stickers));
|
83
72
|
}
|
84
|
-
for (
|
73
|
+
for (long y = 0; y < n; ++y) {
|
85
74
|
const VALUE row = rb_ary_entry(stickers, y);
|
86
75
|
Check_Type(row, T_ARRAY);
|
87
76
|
if (RARRAY_LEN(row) != n) {
|
88
77
|
rb_raise(rb_eArgError, "All rows of a %ldx%ld cube must have %ld cells. Got %ld cells.", n, n, n, RARRAY_LEN(row));
|
89
78
|
}
|
90
|
-
for (
|
79
|
+
for (long x = 0; x < n; ++x) {
|
91
80
|
const VALUE cell = rb_ary_entry(row, x);
|
92
81
|
Point point = {x, y};
|
93
82
|
data->stickers[sticker_index(n, on_face_index, point)] = cell;
|
@@ -99,7 +88,8 @@ static int CubeState_replace_face(const VALUE key, const VALUE value, const VALU
|
|
99
88
|
static VALUE CubeState_initialize(const VALUE self, const VALUE cube_size, const VALUE stickers) {
|
100
89
|
Check_Type(cube_size, T_FIXNUM);
|
101
90
|
Check_Type(stickers, T_HASH);
|
102
|
-
const
|
91
|
+
const long n = FIX2INT(cube_size);
|
92
|
+
check_cube_size(n);
|
103
93
|
CubeStateData* data;
|
104
94
|
GetCubeStateData(self, data);
|
105
95
|
data->cube_size = n;
|
@@ -127,11 +117,11 @@ static VALUE CubeState_sticker_array(const VALUE self,
|
|
127
117
|
check_base_face_indices(on_face_index, x_base_face_index, y_base_face_index);
|
128
118
|
const CubeStateData* data;
|
129
119
|
GetInitializedCubeStateData(self, data);
|
130
|
-
const
|
120
|
+
const long n = data->cube_size;
|
131
121
|
const VALUE face = rb_ary_new2(n);
|
132
|
-
for (
|
122
|
+
for (long y = 0; y < n; ++y) {
|
133
123
|
const VALUE row = rb_ary_new2(n);
|
134
|
-
for (
|
124
|
+
for (long x = 0; x < n; ++x) {
|
135
125
|
const Point point = point_on_face(on_face_index, x_base_face_index, y_base_face_index, n, x, y);
|
136
126
|
const VALUE cell = data->stickers[sticker_index(n, on_face_index, point)];
|
137
127
|
rb_ary_store(row, x, cell);
|
@@ -159,7 +149,7 @@ static VALUE CubeState_hash(const VALUE self) {
|
|
159
149
|
|
160
150
|
st_index_t hash = rb_hash_start(data->cube_size);
|
161
151
|
hash = rb_hash_uint(hash, (st_index_t)CubeState_hash);
|
162
|
-
const
|
152
|
+
const long n = data->cube_size;
|
163
153
|
for (size_t i = 0; i < num_stickers(n); i++) {
|
164
154
|
const VALUE sub_hash = rb_hash(data->stickers[i]);
|
165
155
|
hash = rb_hash_uint(hash, NUM2LONG(sub_hash));
|
@@ -181,7 +171,7 @@ static VALUE CubeState_eql(const VALUE self, const VALUE other) {
|
|
181
171
|
if (self_data->cube_size != other_data->cube_size) {
|
182
172
|
return Qfalse;
|
183
173
|
}
|
184
|
-
const
|
174
|
+
const long n = self_data->cube_size;
|
185
175
|
for (size_t i = 0; i < num_stickers(n); ++i) {
|
186
176
|
if (!color_eq(self_data->stickers[i], other_data->stickers[i])) {
|
187
177
|
return Qfalse;
|
@@ -193,7 +183,7 @@ static VALUE CubeState_eql(const VALUE self, const VALUE other) {
|
|
193
183
|
static VALUE CubeState_dup(const VALUE self) {
|
194
184
|
const CubeStateData* data;
|
195
185
|
GetInitializedCubeStateData(self, data);
|
196
|
-
const
|
186
|
+
const long n = data->cube_size;
|
197
187
|
CubeStateData* dupped_data;
|
198
188
|
const VALUE dupped = TypedData_Make_Struct(rb_obj_class(self), CubeStateData, &CubeStateData_type, dupped_data);
|
199
189
|
dupped_data->cube_size = n;
|
@@ -208,19 +198,19 @@ static VALUE CubeState_cube_size(const VALUE self) {
|
|
208
198
|
return ST2FIX(data->cube_size);
|
209
199
|
}
|
210
200
|
|
211
|
-
void rotate_slice_for_cube(const face_index_t turned_face_index, const
|
201
|
+
void rotate_slice_for_cube(const face_index_t turned_face_index, const long slice_index, direction_t direction, const CubeStateData* const data) {
|
212
202
|
direction = CROP_MOD(direction, 4);
|
213
203
|
if (direction == 0) {
|
214
204
|
return;
|
215
205
|
}
|
216
|
-
const
|
217
|
-
for (
|
206
|
+
const long n = data->cube_size;
|
207
|
+
for (long x = 0; x < n; ++x) {
|
218
208
|
Sticker4Cycle cycle;
|
219
|
-
for (size_t
|
220
|
-
const face_index_t on_face_index = neighbor_face_index(turned_face_index,
|
221
|
-
const face_index_t next_face_index = neighbor_face_index(turned_face_index,
|
222
|
-
const Point point = point_on_face(on_face_index, turned_face_index, next_face_index, n, slice_index,
|
223
|
-
cycle.indices[
|
209
|
+
for (size_t i = 0; i < neighbor_faces; ++i) {
|
210
|
+
const face_index_t on_face_index = neighbor_face_index(turned_face_index, i);
|
211
|
+
const face_index_t next_face_index = neighbor_face_index(turned_face_index, i + 1);
|
212
|
+
const Point point = point_on_face(on_face_index, turned_face_index, next_face_index, n, slice_index, x);
|
213
|
+
cycle.indices[i] = sticker_index(n, on_face_index, point);
|
224
214
|
}
|
225
215
|
apply_sticker_4cycle(data->stickers, cycle, direction);
|
226
216
|
}
|
@@ -231,9 +221,9 @@ void rotate_face_for_cube(const face_index_t turned_face_index, direction_t dire
|
|
231
221
|
if (direction == 0) {
|
232
222
|
return;
|
233
223
|
}
|
234
|
-
const
|
235
|
-
for (
|
236
|
-
for (
|
224
|
+
const long n = data->cube_size;
|
225
|
+
for (long y = 0; y < n / 2; ++y) {
|
226
|
+
for (long x = 0; x < (n + 1) / 2; ++x) {
|
237
227
|
Sticker4Cycle cycle;
|
238
228
|
for (size_t j = 0; j < neighbor_faces; ++j) {
|
239
229
|
const face_index_t x_face_index = neighbor_face_index(turned_face_index, j);
|
@@ -5,7 +5,7 @@
|
|
5
5
|
#include "face_symbols.h"
|
6
6
|
|
7
7
|
typedef struct {
|
8
|
-
|
8
|
+
long cube_size;
|
9
9
|
VALUE* stickers;
|
10
10
|
} CubeStateData;
|
11
11
|
|
@@ -24,7 +24,7 @@ extern const rb_data_type_t CubeStateData_type;
|
|
24
24
|
} \
|
25
25
|
} while(0)
|
26
26
|
|
27
|
-
void rotate_slice_for_cube(face_index_t turned_face_index,
|
27
|
+
void rotate_slice_for_cube(face_index_t turned_face_index, long slice_index, direction_t direction, const CubeStateData* data);
|
28
28
|
|
29
29
|
void rotate_face_for_cube(face_index_t turned_face_index, direction_t direction, const CubeStateData* data);
|
30
30
|
|
@@ -50,15 +50,6 @@ const rb_data_type_t SkewbAlgorithmData_type = {
|
|
50
50
|
RUBY_TYPED_FREE_IMMEDIATELY
|
51
51
|
};
|
52
52
|
|
53
|
-
static void check_moves(const SkewbAlgorithmData* const data, const char* const name) {
|
54
|
-
for (size_t i = 0; i < data->size; ++i) {
|
55
|
-
const SkewbMoveType type = data->moves[i].type;
|
56
|
-
if (type != MOVE && type != ROTATION) {
|
57
|
-
rb_raise(rb_eRuntimeError, "invalid move type %d in %s", type, name);
|
58
|
-
}
|
59
|
-
}
|
60
|
-
}
|
61
|
-
|
62
53
|
static SkewbMove* malloc_moves(const size_t n) {
|
63
54
|
SkewbMove* const moves = malloc(n * sizeof(SkewbMove));
|
64
55
|
if (moves == NULL) {
|
@@ -122,7 +113,7 @@ static VALUE SkewbAlgorithm_initialize(const VALUE self, const VALUE moves) {
|
|
122
113
|
data->size = RARRAY_LEN(moves);
|
123
114
|
data->initialized = TRUE;
|
124
115
|
data->moves = malloc_moves(data->size);
|
125
|
-
for (
|
116
|
+
for (long i = 0; i < RARRAY_LEN(moves); ++i) {
|
126
117
|
const VALUE move = rb_ary_entry(moves, i);
|
127
118
|
if (RARRAY_LEN(move) != 3) {
|
128
119
|
rb_raise(rb_eArgError, "Moves must have 3 elements. Got %ld.", RARRAY_LEN(moves));
|
@@ -171,8 +162,8 @@ static face_index_t axis_face_on_corner(const Corner corner, const face_index_t
|
|
171
162
|
|
172
163
|
bool corners_eq(Corner left, Corner right) {
|
173
164
|
return left.face_indices[0] == right.face_indices[0] &&
|
174
|
-
(left.face_indices[1] == right.face_indices[1] && left.face_indices[2] == right.face_indices[2] ||
|
175
|
-
left.face_indices[1] == right.face_indices[2] && left.face_indices[2] == right.face_indices[1]);
|
165
|
+
((left.face_indices[1] == right.face_indices[1] && left.face_indices[2] == right.face_indices[2]) ||
|
166
|
+
(left.face_indices[1] == right.face_indices[2] && left.face_indices[2] == right.face_indices[1]));
|
176
167
|
}
|
177
168
|
|
178
169
|
size_t equivalent_corner_index(const FaceCorners corners, const Corner corner) {
|
@@ -56,17 +56,6 @@ size_t center_sticker_index(const face_index_t on_face_index) {
|
|
56
56
|
return on_face_index * skewb_stickers_per_face;
|
57
57
|
}
|
58
58
|
|
59
|
-
static VALUE part_type_from_symbol(const VALUE part_type_symbol) {
|
60
|
-
Check_Type(face_symbol, T_SYMBOL);
|
61
|
-
if (SYM2ID(part_type_symbol) == center_part_type_id) {
|
62
|
-
return CENTER;
|
63
|
-
} else if (SYM2ID(part_type_symbol) == corner_part_type_id) {
|
64
|
-
return CORNER;
|
65
|
-
} else {
|
66
|
-
rb_raise(rb_eArgError, "Invalid part type symbol %+"PRIsVALUE"", part_type_symbol);
|
67
|
-
}
|
68
|
-
}
|
69
|
-
|
70
59
|
static VALUE part_type_to_symbol(const SkewbPartType part_type) {
|
71
60
|
// Caching these keys isn't easy because the garbage collector will get them.
|
72
61
|
switch (part_type) {
|
@@ -32,7 +32,7 @@ static ID times = 848;
|
|
32
32
|
|
33
33
|
typedef struct {
|
34
34
|
Corner corner_pairs[max_corner_pair_group_size][2];
|
35
|
-
|
35
|
+
size_t num_corner_pairs;
|
36
36
|
// Number of different group fingerprints. This can be used to merge several group fingerprints.
|
37
37
|
int num_group_fingerprints;
|
38
38
|
} CornerPairGroup;
|
@@ -55,7 +55,7 @@ static bool has_color_at(const ActualCornerStickers actual, const size_t index,
|
|
55
55
|
}
|
56
56
|
|
57
57
|
typedef struct {
|
58
|
-
|
58
|
+
size_t layer_index;
|
59
59
|
bool is_oriented;
|
60
60
|
bool is_present;
|
61
61
|
} ActualCornerStickersInfo;
|
@@ -268,4 +268,5 @@ void init_skewb_layer_fingerprint_method_under(const VALUE module) {
|
|
268
268
|
plus = rb_intern("+");
|
269
269
|
times = rb_intern("*");
|
270
270
|
rb_define_singleton_method(module, "skewb_layer_fingerprint", skewb_layer_fingerprint, 2);
|
271
|
+
init_corner_pair_groups();
|
271
272
|
}
|
@@ -43,8 +43,6 @@ static int SkewbState_replace_face(const VALUE key, const VALUE value, const VAL
|
|
43
43
|
|
44
44
|
static VALUE SkewbState_initialize(const VALUE self, const VALUE stickers) {
|
45
45
|
Check_Type(stickers, T_HASH);
|
46
|
-
SkewbStateData* data;
|
47
|
-
GetSkewbStateData(self, data);
|
48
46
|
if (RHASH_SIZE(stickers) != skewb_faces) {
|
49
47
|
rb_raise(rb_eTypeError, "Skewbs must have %d faces. Got %ld.", skewb_faces, RHASH_SIZE(stickers));
|
50
48
|
}
|
@@ -64,7 +64,7 @@ int log2_64_floor(uint64_t value) {
|
|
64
64
|
return tab64[((uint64_t)((value - (value >> 1))*0x07EDD5E59A4E28C2)) >> 58];
|
65
65
|
}
|
66
66
|
|
67
|
-
uint64_t iexp(const uint64_t base, uint32_t exp) {
|
67
|
+
uint64_t iexp(const uint64_t base, const uint32_t exp) {
|
68
68
|
uint64_t result = 1;
|
69
69
|
for (uint32_t m = 1 << 31; m; m >>= 1) {
|
70
70
|
result = result * result;
|
@@ -74,3 +74,9 @@ uint64_t iexp(const uint64_t base, uint32_t exp) {
|
|
74
74
|
}
|
75
75
|
return result;
|
76
76
|
}
|
77
|
+
|
78
|
+
void check_cube_size(const long cube_size) {
|
79
|
+
if (cube_size <= 0) {
|
80
|
+
rb_raise(rb_eArgError, "Cube size must be positive. Got %ld.", cube_size);
|
81
|
+
}
|
82
|
+
}
|