twisty_puzzles 0.0.4 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +6 -1
  4. data/ext/twisty_puzzles/native/cube_algorithm.c +10 -18
  5. data/ext/twisty_puzzles/native/cube_average.c +2 -2
  6. data/ext/twisty_puzzles/native/cube_coordinate.c +16 -15
  7. data/ext/twisty_puzzles/native/cube_coordinate.h +7 -7
  8. data/ext/twisty_puzzles/native/cube_state.c +23 -33
  9. data/ext/twisty_puzzles/native/cube_state.h +2 -2
  10. data/ext/twisty_puzzles/native/face_symbols.h +2 -2
  11. data/ext/twisty_puzzles/native/skewb_algorithm.c +3 -12
  12. data/ext/twisty_puzzles/native/skewb_coordinate.c +0 -11
  13. data/ext/twisty_puzzles/native/skewb_layer_fingerprint.c +3 -2
  14. data/ext/twisty_puzzles/native/skewb_state.c +0 -2
  15. data/ext/twisty_puzzles/native/utils.c +7 -1
  16. data/ext/twisty_puzzles/native/utils.h +2 -3
  17. data/lib/twisty_puzzles.rb +1 -0
  18. data/lib/twisty_puzzles/abstract_move.rb +1 -2
  19. data/lib/twisty_puzzles/abstract_move_parser.rb +1 -1
  20. data/lib/twisty_puzzles/algorithm.rb +1 -1
  21. data/lib/twisty_puzzles/axis_face_and_direction_move.rb +1 -0
  22. data/lib/twisty_puzzles/cancellation_helper.rb +1 -1
  23. data/lib/twisty_puzzles/color_scheme.rb +1 -1
  24. data/lib/twisty_puzzles/commutator.rb +3 -0
  25. data/lib/twisty_puzzles/compiled_algorithm.rb +4 -4
  26. data/lib/twisty_puzzles/coordinate.rb +23 -6
  27. data/lib/twisty_puzzles/cube.rb +3 -3
  28. data/lib/twisty_puzzles/cube_move.rb +0 -4
  29. data/lib/twisty_puzzles/cube_move_parser.rb +23 -23
  30. data/lib/twisty_puzzles/cube_print_helper.rb +4 -3
  31. data/lib/twisty_puzzles/parser.rb +3 -3
  32. data/lib/twisty_puzzles/rotation.rb +2 -0
  33. data/lib/twisty_puzzles/skewb_move.rb +1 -0
  34. data/lib/twisty_puzzles/skewb_move_parser.rb +1 -0
  35. data/lib/twisty_puzzles/skewb_notation.rb +7 -1
  36. data/lib/twisty_puzzles/version.rb +1 -1
  37. metadata +11 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9b1eef6907e1eced49a2341827ff269501861ba6bcd6e80f8b8a47be078cf2b
4
- data.tar.gz: 954d9c2e59e038a4a65b4073ddad86669109bc5dabcf7b0f7b0efa26983156d0
3
+ metadata.gz: 3dfb23949825572c531ac7bfcea491151629f8673160605069b1793a827d961a
4
+ data.tar.gz: f343cc589e99ac129717f47a7b3dbe4dcb3d4a0cbcae2e0f8c42b12b22ad842c
5
5
  SHA512:
6
- metadata.gz: ed59dd840b46359c2ab410325238d2634aede069afe1544df11a5c5adf2e99c6648f1776543d563ddc87937c9f73da7f185cc3ed2b52f0baf86a8c1419b89ccf
7
- data.tar.gz: 6c67856ad23e2b99137d31c0a183c8b811caecf9f401215aecb6c58de3825e7754d9ba02aab6c275c37d511f7b5f4f90b5744e2318b91efb6f2ef24013c9976d
6
+ metadata.gz: 2fc20aef94e333318c53ee292b5418424ad8880cc2f8ff18c2102d0799d96728ccc9a98869269bf9c6a046174dcf5f71182cf6498021838d8772c18a7008cfe2
7
+ data.tar.gz: b79344d44bf6fd32cd9443c79405dcab052867a746e23fecc0b1496bd96b36fc6c4dd09d2a8c3d33389d7e5b5daaf0ca4a0552cce8948c59ac590da458c6150d
data/CHANGELOG.md CHANGED
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.0.5]
8
+ ### Changed
9
+ - Now `require 'twisty_puzzles'` also requires the native extensions.
10
+
7
11
  ## [0.0.4]
8
12
  ### Fixed
9
13
  Fixed path in extconf.
data/README.md CHANGED
@@ -1,3 +1,8 @@
1
+ ![Ruby](https://github.com/Lykos/twisty_puzzles/workflows/Ruby/badge.svg)
2
+ ![Rubocop](https://github.com/Lykos/twisty_puzzles/workflows/Rubocop/badge.svg)
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Gem Version](https://badge.fury.io/rb/twisty_puzzles.svg)](https://badge.fury.io/rb/twisty_puzzles)
5
+
1
6
  # Twisty Puzzles
2
7
  Gem for my cube_trainer rails app. Some things are better left in a separate gem with no rails, e.g. native extensions. The main purpose is to support my Rails app, but if it's useful for someone else, feel free to use it at your own risk.
3
8
 
@@ -25,7 +30,7 @@ TODO: Write usage instructions here
25
30
 
26
31
  After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rake spec` to run the tests. You can also run `bundle exec bin/console` for an interactive prompt that will allow you to experiment.
27
32
 
28
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
33
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `lib/twisty_puzzles/version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
29
34
 
30
35
  ## Contributing
31
36
 
@@ -18,12 +18,12 @@ typedef struct {
18
18
  CubeMoveType type;
19
19
  face_index_t axis_face_index;
20
20
  direction_t direction;
21
- size_t slice_index;
21
+ long slice_index;
22
22
  } CubeMove;
23
23
 
24
24
  typedef struct {
25
25
  size_t size;
26
- size_t cube_size;
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 size_t components_for_move_type(const CubeMoveType type) {
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 = NUM2INT(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 (size_t i = 0; i < RARRAY_LEN(moves); ++i) {
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 size_t num_components = components_for_move_type(type);
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 = NUM2INT(rb_ary_entry(move, 2));
121
+ data->moves[i].direction = FIX2INT(rb_ary_entry(move, 2));
130
122
  if (type == SLICE) {
131
- const size_t slice_index = NUM2INT(rb_ary_entry(move, 3));
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 size_t n = FIX2INT(capacity);
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 (size_t i = start; i < RARRAY_LEN(new_values); ++i) {
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
- size_t cube_size;
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 size_t cube_size) {
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 size_t cube_size, const face_index_t on_face_index, const Point point) {
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 size_t cube_size) {
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 size_t inverted_index(const size_t cube_size, const size_t index) {
56
+ static long inverted_index(const long cube_size, const long index) {
57
57
  return cube_size - 1 - index;
58
58
  }
59
59
 
60
- size_t transform_index(const face_index_t index_base_face_index, const size_t cube_size, const size_t index) {
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 size_t cube_size,
90
- const size_t untransformed_x,
91
- const size_t untransformed_y) {
92
- const size_t transformed_x = transform_index(x_base_face_index, cube_size, untransformed_x);
93
- const size_t transformed_y = transform_index(y_base_face_index, cube_size, untransformed_y);
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 size_t cube_size, const size_t index) {
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 size_t n = FIX2INT(cube_size);
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 size_t untransformed_x = FIX2INT(x_num);
130
+ const long untransformed_x = FIX2INT(x_num);
130
131
  check_cube_index(n, untransformed_x);
131
- const size_t untransformed_y = FIX2INT(y_num);
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(size_t cube_size);
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(size_t cube_size, face_index_t on_face_index, Point point);
15
+ size_t sticker_index(long cube_size, face_index_t on_face_index, Point point);
16
16
 
17
- size_t transform_index(face_index_t index_base_face_index, size_t cube_size, size_t index);
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
- size_t cube_size,
29
- size_t untransformed_x,
30
- size_t untransformed_y);
28
+ long cube_size,
29
+ long untransformed_x,
30
+ long untransformed_y);
31
31
 
32
- size_t CubeCoordinate_sticker_index(VALUE self, size_t cube_size);
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 size_t n = data->cube_size;
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 size_t n = data->cube_size;
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 (size_t y = 0; y < n; ++y) {
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 (size_t x = 0; x < n; ++x) {
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 size_t n = FIX2INT(cube_size);
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 size_t n = data->cube_size;
120
+ const long n = data->cube_size;
131
121
  const VALUE face = rb_ary_new2(n);
132
- for (size_t y = 0; y < n; ++y) {
122
+ for (long y = 0; y < n; ++y) {
133
123
  const VALUE row = rb_ary_new2(n);
134
- for (size_t x = 0; x < n; ++x) {
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 size_t n = data->cube_size;
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 size_t n = self_data->cube_size;
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 size_t n = data->cube_size;
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 size_t slice_index, direction_t direction, const CubeStateData* const data) {
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 size_t n = data->cube_size;
217
- for (size_t i = 0; i < n; ++i) {
206
+ const long n = data->cube_size;
207
+ for (long x = 0; x < n; ++x) {
218
208
  Sticker4Cycle cycle;
219
- for (size_t j = 0; j < neighbor_faces; ++j) {
220
- const face_index_t on_face_index = neighbor_face_index(turned_face_index, j);
221
- const face_index_t next_face_index = neighbor_face_index(turned_face_index, j + 1);
222
- const Point point = point_on_face(on_face_index, turned_face_index, next_face_index, n, slice_index, i);
223
- cycle.indices[j] = sticker_index(n, on_face_index, point);
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 size_t n = data->cube_size;
235
- for (size_t y = 0; y < n / 2; ++y) {
236
- for (size_t x = 0; x < (n + 1) / 2; ++x) {
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
- size_t cube_size;
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, size_t slice_index, direction_t direction, const CubeStateData* data);
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
 
@@ -4,8 +4,8 @@
4
4
 
5
5
  #include "utils.h"
6
6
 
7
- typedef char face_index_t;
8
- typedef char axis_index_t;
7
+ typedef unsigned char face_index_t;
8
+ typedef unsigned char axis_index_t;
9
9
 
10
10
  #define cube_faces 6
11
11
  #define neighbor_faces 4
@@ -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 (size_t i = 0; i < RARRAY_LEN(moves); ++i) {
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
- int num_corner_pairs;
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
- int layer_index;
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
+ }
@@ -5,11 +5,8 @@
5
5
 
6
6
  #define MIN(a, b) ((a) > (b) ? (b) : (a))
7
7
  #define MAX(a, b) ((a) > (b) ? (a) : (b))
8
- #define FALSE 0
9
- #define TRUE 1
10
8
  #define CROP_MOD(a, b) (((a) % (b) + (b)) % (b))
11
9
 
12
- typedef char bool;
13
10
  typedef char direction_t;
14
11
 
15
12
  typedef struct {
@@ -29,3 +26,5 @@ int color_eq(VALUE left, VALUE right);
29
26
  int log2_64_floor(uint64_t value);
30
27
 
31
28
  uint64_t iexp(uint64_t base, uint32_t exp);
29
+
30
+ void check_cube_size(long cube_size);
@@ -22,6 +22,7 @@ require 'twisty_puzzles/cube_print_helper'
22
22
  require 'twisty_puzzles/cube_state'
23
23
  require 'twisty_puzzles/letter_scheme'
24
24
  require 'twisty_puzzles/move_type_creator'
25
+ require 'twisty_puzzles/native'
25
26
  require 'twisty_puzzles/parser'
26
27
  require 'twisty_puzzles/part_cycle_factory'
27
28
  require 'twisty_puzzles/puzzle'
@@ -150,8 +150,7 @@ module TwistyPuzzles
150
150
  when :qtm then slice_factor * direction_factor
151
151
  when :htm then slice_factor
152
152
  when :stm then 1
153
- when :qstm then direction_factor
154
- when :sqtm then direction_factor
153
+ when :qstm, :sqtm then direction_factor
155
154
  else raise ArgumentError, "Invalid move metric #{metric.inspect}."
156
155
  end
157
156
  end
@@ -20,7 +20,7 @@ module TwistyPuzzles
20
20
  end
21
21
 
22
22
  def parse_named_captures(match)
23
- present_named_captures = match.named_captures.reject { |_n, v| v.nil? }
23
+ present_named_captures = match.named_captures.compact
24
24
  present_named_captures.map do |name, string|
25
25
  key = parse_part_key(name).to_sym
26
26
  value = parse_move_part(name, string)
@@ -128,7 +128,7 @@ module TwistyPuzzles
128
128
  AbstractMove.check_move_metric(metric)
129
129
  return 0 if empty?
130
130
 
131
- @moves.map { |m| m.move_count(cube_size, metric) }.reduce(:+)
131
+ @moves.sum { |m| m.move_count(cube_size, metric) }
132
132
  end
133
133
 
134
134
  def *(other)
@@ -11,6 +11,7 @@ module TwistyPuzzles
11
11
  raise TypeError, "Unsuitable axis face #{axis_face}." unless axis_face.is_a?(Face)
12
12
  raise TypeError unless direction.is_a?(CubeDirection)
13
13
 
14
+ super()
14
15
  @axis_face = axis_face
15
16
  @direction = direction
16
17
  end
@@ -135,7 +135,7 @@ module TwistyPuzzles
135
135
  def self.alg_plus_cancelled_move(algorithm, move, cube_size)
136
136
  if move.is_a?(Rotation) && (tail_rotations = num_tail_rotations(algorithm)) >= 2
137
137
  Algorithm.new(algorithm.moves[0...-tail_rotations]) +
138
- cancelled_rotations(algorithm.moves[-tail_rotations..-1] + [move])
138
+ cancelled_rotations(algorithm.moves[-tail_rotations..] + [move])
139
139
  else
140
140
  Algorithm.new(algorithm.moves[0...-1]) +
141
141
  algorithm.moves[-1].join_with_cancellation(move, cube_size)
@@ -56,7 +56,7 @@ module TwistyPuzzles
56
56
  raise ArgumentError unless colors.include?(top_color)
57
57
  raise ArgumentError unless colors.include?(front_color)
58
58
 
59
- # Note: The reason that this is so complicated is that we want it to still work if the
59
+ # NOTE: The reason that this is so complicated is that we want it to still work if the
60
60
  # chirality corner gets exchanged.
61
61
 
62
62
  # Do the obvious and handle opposites of the top and front color so we have no
@@ -17,6 +17,7 @@ module TwistyPuzzles
17
17
  def initialize(algorithm)
18
18
  raise ArgumentError unless algorithm.is_a?(Algorithm)
19
19
 
20
+ super()
20
21
  @algorithm = algorithm
21
22
  end
22
23
 
@@ -47,6 +48,7 @@ module TwistyPuzzles
47
48
  raise ArgumentError unless first_part.is_a?(Algorithm)
48
49
  raise ArgumentError unless second_part.is_a?(Algorithm)
49
50
 
51
+ super()
50
52
  @first_part = first_part
51
53
  @second_part = second_part
52
54
  end
@@ -85,6 +87,7 @@ module TwistyPuzzles
85
87
  raise ArgumentError, 'Inner commutator has to be a commutator.'
86
88
  end
87
89
 
90
+ super()
88
91
  @setup = setup
89
92
  @inner_commutator = inner_commutator
90
93
  end
@@ -26,10 +26,10 @@ module TwistyPuzzles
26
26
  def inverse
27
27
  @inverse ||=
28
28
  begin
29
- alg = self.class.new(@native.inverse)
30
- alg.inverse = self
31
- alg
32
- end
29
+ alg = self.class.new(@native.inverse)
30
+ alg.inverse = self
31
+ alg
32
+ end
33
33
  end
34
34
 
35
35
  def +(other)
@@ -6,6 +6,7 @@ require 'twisty_puzzles/native'
6
6
 
7
7
  module TwistyPuzzles
8
8
  # Coordinate of a sticker on the cube.
9
+ # rubocop:disable Metrics/ClassLength
9
10
  class Coordinate
10
11
  def self.highest_coordinate(cube_size)
11
12
  cube_size - 1
@@ -90,7 +91,7 @@ module TwistyPuzzles
90
91
  base_coordinate = Coordinate.from_indices(
91
92
  part.solved_face, cube_size, *part.base_index_on_face(cube_size, incarnation_index)
92
93
  )
93
- other_face_symbols = part.corresponding_part.face_symbols[1..-1]
94
+ other_face_symbols = part.corresponding_part.face_symbols[1..]
94
95
  match_coordinate_internal(base_coordinate, other_face_symbols)
95
96
  end
96
97
 
@@ -99,7 +100,7 @@ module TwistyPuzzles
99
100
  def self.solved_positions(part, cube_size, incarnation_index)
100
101
  solved_coordinate = solved_position(part, cube_size, incarnation_index)
101
102
  other_coordinates =
102
- part.face_symbols[1..-1].map.with_index do |f, i|
103
+ part.face_symbols[1..].map.with_index do |f, i|
103
104
  face = Face.for_face_symbol(f)
104
105
  # The reverse is important for edge like parts. We are not in the same position as usual
105
106
  # solved pieces would be.
@@ -109,7 +110,7 @@ module TwistyPuzzles
109
110
  base_coordinate = Coordinate.from_indices(face, cube_size, *base_indices)
110
111
  other_face_symbols = [part.face_symbols[0]] +
111
112
  part.corresponding_part.face_symbols[1...i + 1] +
112
- part.corresponding_part.face_symbols[i + 2..-1]
113
+ part.corresponding_part.face_symbols[i + 2..]
113
114
  match_coordinate_internal(base_coordinate, other_face_symbols)
114
115
  end
115
116
  [solved_coordinate] + other_coordinates
@@ -121,6 +122,23 @@ module TwistyPuzzles
121
122
  from_indices(face, cube_size, m, m)
122
123
  end
123
124
 
125
+ def self.face(face, cube_size)
126
+ neighbor_a, neighbor_b = face.neighbors[0..1]
127
+ coordinate_range(cube_size).collect_concat do |x|
128
+ coordinate_range(cube_size).map do |y|
129
+ from_face_distances(face, cube_size, neighbor_a => x, neighbor_b => y)
130
+ end
131
+ end
132
+ end
133
+
134
+ def self.layer(face, cube_size)
135
+ face.neighbors.zip(face.neighbors.rotate(1)).collect_concat do |neighbor, next_neighbor|
136
+ coordinate_range(cube_size).map do |i|
137
+ from_face_distances(neighbor, cube_size, face => 0, next_neighbor => i)
138
+ end
139
+ end + self.face(face, cube_size)
140
+ end
141
+
124
142
  def self.edges_outside(face, cube_size)
125
143
  face.neighbors.zip(face.neighbors.rotate(1)).collect_concat do |neighbor, next_neighbor|
126
144
  1.upto(cube_size - 2).map do |i|
@@ -261,6 +279,7 @@ module TwistyPuzzles
261
279
  rots
262
280
  end
263
281
  end
282
+ # rubocop:enable Metrics/ClassLength
264
283
 
265
284
  # Coordinate of a sticker on the Skewb.
266
285
  class SkewbCoordinate
@@ -276,7 +295,7 @@ module TwistyPuzzles
276
295
  @native = native
277
296
  end
278
297
 
279
- attr_reader :native
298
+ attr_reader :native, :coordinate
280
299
 
281
300
  private_class_method :new
282
301
 
@@ -311,7 +330,5 @@ module TwistyPuzzles
311
330
  def face
312
331
  @face ||= Face.for_face_symbol(@native.face)
313
332
  end
314
-
315
- attr_reader :coordinate
316
333
  end
317
334
  end
@@ -97,7 +97,7 @@ module TwistyPuzzles
97
97
  end
98
98
 
99
99
  def inspect
100
- self.class.to_s + '(' + @face_symbols.map(&:to_s).join(', ') + ')'
100
+ "#{self.class}(#{@face_symbols.map(&:to_s).join(', ')})"
101
101
  end
102
102
 
103
103
  def to_s
@@ -365,7 +365,7 @@ module TwistyPuzzles
365
365
  attr_reader :corresponding_part
366
366
 
367
367
  def inspect
368
- self.class.to_s + '(' + face_symbol.to_s + ', ' + @corresponding_part.inspect + ')'
368
+ "#{self.class}(#{face_symbol}, #{@corresponding_part.inspect})"
369
369
  end
370
370
 
371
371
  def rotate_by(_number)
@@ -532,7 +532,7 @@ module TwistyPuzzles
532
532
 
533
533
  def self.create_for_face_symbols(face_symbols)
534
534
  piece_candidates =
535
- face_symbols[1..-1].permutation.map do |cs|
535
+ face_symbols[1..].permutation.map do |cs|
536
536
  new([face_symbols[0]] + cs)
537
537
  end
538
538
  find_only(piece_candidates, &:valid?)
@@ -139,8 +139,6 @@ module TwistyPuzzles
139
139
  end
140
140
  end
141
141
 
142
- # rubocop:disable Metrics/PerceivedComplexity
143
- # rubocop:disable Metrics/CyclomaticComplexity
144
142
  def prepend_fat_move(other, cube_size)
145
143
  if same_fat_block?(other)
146
144
  merge_with_same_fat_block(other)
@@ -156,8 +154,6 @@ module TwistyPuzzles
156
154
  Algorithm.move(other.inner_fat_mslice_move(cube_size))
157
155
  end
158
156
  end
159
- # rubocop:enable Metrics/CyclomaticComplexity
160
- # rubocop:enable Metrics/PerceivedComplexity
161
157
 
162
158
  def prepend_slice_move(other, cube_size)
163
159
  return unless same_axis?(other)
@@ -14,29 +14,29 @@ module TwistyPuzzles
14
14
  class CubeMoveParser < AbstractMoveParser
15
15
  REGEXP =
16
16
  begin
17
- axes_part = "(?<axis_name>[#{AbstractMove::AXES.join}])"
18
- face_names = CubeConstants::FACE_NAMES.join
19
- fat_move_part =
20
- "(?<width>\\d*)(?<fat_face_name>[#{face_names}])w"
21
- normal_move_part = "(?<face_name>[#{face_names}])"
22
- downcased_face_names = face_names.downcase
23
- maybe_fat_maybe_slice_move_part =
24
- "(?<maybe_fat_face_maybe_slice_name>[#{downcased_face_names}])"
25
- slice_move_part =
26
- "(?<slice_index>\\d+)(?<slice_name>[#{downcased_face_names}])"
27
- mslice_move_part =
28
- "(?<mslice_name>[#{AbstractMove::SLICE_FACES.keys.join}])"
29
- move_part = "(?:#{axes_part}|" \
30
- "#{fat_move_part}|" \
31
- "#{normal_move_part}|" \
32
- "#{maybe_fat_maybe_slice_move_part}|" \
33
- "#{slice_move_part}|#{mslice_move_part})"
34
- direction_names =
35
- AbstractDirection::POSSIBLE_DIRECTION_NAMES.flatten
36
- direction_names.sort_by! { |e| -e.length }
37
- direction_part = "(?<direction>#{direction_names.join('|')})"
38
- Regexp.new("#{move_part}#{direction_part}")
39
- end
17
+ axes_part = "(?<axis_name>[#{AbstractMove::AXES.join}])"
18
+ face_names = CubeConstants::FACE_NAMES.join
19
+ fat_move_part =
20
+ "(?<width>\\d*)(?<fat_face_name>[#{face_names}])w"
21
+ normal_move_part = "(?<face_name>[#{face_names}])"
22
+ downcased_face_names = face_names.downcase
23
+ maybe_fat_maybe_slice_move_part =
24
+ "(?<maybe_fat_face_maybe_slice_name>[#{downcased_face_names}])"
25
+ slice_move_part =
26
+ "(?<slice_index>\\d+)(?<slice_name>[#{downcased_face_names}])"
27
+ mslice_move_part =
28
+ "(?<mslice_name>[#{AbstractMove::SLICE_FACES.keys.join}])"
29
+ move_part = "(?:#{axes_part}|" \
30
+ "#{fat_move_part}|" \
31
+ "#{normal_move_part}|" \
32
+ "#{maybe_fat_maybe_slice_move_part}|" \
33
+ "#{slice_move_part}|#{mslice_move_part})"
34
+ direction_names =
35
+ AbstractDirection::POSSIBLE_DIRECTION_NAMES.flatten
36
+ direction_names.sort_by! { |e| -e.length }
37
+ direction_part = "(?<direction>#{direction_names.join('|')})"
38
+ Regexp.new("#{move_part}#{direction_part}")
39
+ end
40
40
 
41
41
  MOVE_TYPE_CREATORS = [
42
42
  MoveTypeCreator.new(%i[axis_face direction], Rotation),
@@ -41,9 +41,10 @@ module TwistyPuzzles
41
41
  end
42
42
 
43
43
  def maybe_reverse(reverse_mode, stuff)
44
- if reverse_mode == :reverse
44
+ case reverse_mode
45
+ when :reverse
45
46
  stuff.reverse
46
- elsif reverse_mode == :keep
47
+ when :keep
47
48
  stuff
48
49
  else
49
50
  raise
@@ -102,7 +103,7 @@ module TwistyPuzzles
102
103
  face_symbol_info = FACE_SYMBOL_INFOS[face_symbol]
103
104
  stickers = cube_state.sticker_array(face)
104
105
  center_color = color_character(stickers[0], color_mode)
105
- corner_colors = stickers[1..-1].map { |c| color_character(c, color_mode) }
106
+ corner_colors = stickers[1..].map { |c| color_character(c, color_mode) }
106
107
  permuted_corner_colors =
107
108
  apply_permutation(corner_colors, face_symbol_info.skewb_corner_permutation)
108
109
  raise unless corner_colors.length == 4
@@ -185,14 +185,14 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
185
185
  end
186
186
  end
187
187
 
188
- def parse_commutator(alg_string, complete_parse = true)
188
+ def parse_commutator(alg_string, complete_parse: true)
189
189
  parser = Parser.new(alg_string, CubeMoveParser::INSTANCE)
190
190
  commutator = parser.parse_commutator
191
191
  parser.check_eos('commutator') if complete_parse
192
192
  commutator
193
193
  end
194
194
 
195
- def parse_cube_algorithm(alg_string, complete_parse = true)
195
+ def parse_cube_algorithm(alg_string, complete_parse: true)
196
196
  parser = Parser.new(alg_string, CubeMoveParser::INSTANCE)
197
197
  algorithm = parser.parse_algorithm
198
198
  parser.check_eos('algorithm') if complete_parse
@@ -206,7 +206,7 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
206
206
  alias parse_algorithm parse_cube_algorithm
207
207
  alias parse_move parse_cube_move
208
208
 
209
- def parse_skewb_algorithm(alg_string, notation, complete_parse = true)
209
+ def parse_skewb_algorithm(alg_string, notation, complete_parse: true)
210
210
  parser = Parser.new(alg_string, SkewbMoveParser.new(notation))
211
211
  algorithm = parser.parse_algorithm
212
212
  parser.check_eos('algorithm') if complete_parse
@@ -62,6 +62,7 @@ module TwistyPuzzles
62
62
  [self, alternative].include?(other)
63
63
  end
64
64
 
65
+ # rubocop:disable Metrics/AbcSize
65
66
  def prepend_rotation(other, _cube_size)
66
67
  if same_axis?(other)
67
68
  direction = translated_direction(other.axis_face)
@@ -74,6 +75,7 @@ module TwistyPuzzles
74
75
  Algorithm.move(Rotation.new(remaining_face, CubeDirection::DOUBLE))
75
76
  end
76
77
  end
78
+ # rubocop:enable Metrics/AbcSize
77
79
 
78
80
  def prepend_fat_m_slice_move(_other, _cube_size)
79
81
  nil
@@ -12,6 +12,7 @@ module TwistyPuzzles
12
12
  raise TypeError unless axis_corner.is_a?(Corner)
13
13
  raise TypeError unless direction.is_a?(SkewbDirection)
14
14
 
15
+ super()
15
16
  @axis_corner = axis_corner.rotate_face_up(axis_corner.faces.min_by(&:piece_index))
16
17
  @direction = direction
17
18
  end
@@ -18,6 +18,7 @@ module TwistyPuzzles
18
18
  def initialize(notation)
19
19
  raise TypeError unless notation.is_a?(SkewbNotation)
20
20
 
21
+ super()
21
22
  @notation = notation
22
23
  end
23
24
 
@@ -10,9 +10,11 @@ module TwistyPuzzles
10
10
  # Class that represents one notation for Skewb moves, e.g. Sarahs notation or fixed
11
11
  # corner notation.
12
12
  class SkewbNotation
13
+ # rubocop:disable Metrics/AbcSize
13
14
  def initialize(name, move_corner_pairs)
14
15
  raise TypeError unless name.is_a?(String)
15
16
 
17
+ super()
16
18
  check_move_corner_pairs(move_corner_pairs)
17
19
  @name = name
18
20
  @move_to_corner = move_corner_pairs.to_h.freeze
@@ -26,7 +28,9 @@ module TwistyPuzzles
26
28
  end.freeze
27
29
  freeze
28
30
  end
31
+ # rubocop:enable Metrics/AbcSize
29
32
 
33
+ # rubocop:disable Metrics/CyclomaticComplexity
30
34
  def check_move_corner_pairs(move_corner_pairs)
31
35
  move_corner_pairs.each do |m|
32
36
  raise ArgumentError unless m.length == 2
@@ -37,6 +41,7 @@ module TwistyPuzzles
37
41
 
38
42
  check_corner_coverage(move_corner_pairs.map(&:last))
39
43
  end
44
+ # rubocop:enable Metrics/CyclomaticComplexity
40
45
 
41
46
  def check_corner_coverage(corners)
42
47
  corner_closure = corners + corners.map(&:diagonal_opposite)
@@ -49,6 +54,7 @@ module TwistyPuzzles
49
54
  end
50
55
 
51
56
  attr_reader :name, :move_strings, :non_zero_moves
57
+
52
58
  private_class_method :new
53
59
 
54
60
  def self.fixed_corner
@@ -103,7 +109,7 @@ module TwistyPuzzles
103
109
  move_to_string(m, reversed_rotations)
104
110
  end.join(' ')
105
111
  new_tail_rotations = reversed_rotations.reverse! +
106
- algorithm.moves[algorithm.length - num_tail_rotations..-1]
112
+ algorithm.moves[algorithm.length - num_tail_rotations..]
107
113
  cancelled_rotations = Algorithm.new(new_tail_rotations).cancelled(3)
108
114
  cancelled_rotations.empty? ? alg_string : "#{alg_string} #{cancelled_rotations}"
109
115
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TwistyPuzzles
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.9'
5
5
  end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twisty_puzzles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernhard F. Brodowsky
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2020-04-21 00:00:00.000000000 Z
@@ -112,16 +112,16 @@ dependencies:
112
112
  name: rubocop
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '1.7'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '1.7'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rubocop-performance
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -164,7 +164,7 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
- description:
167
+ description:
168
168
  email: bernhard.brodowsky@gmail.com
169
169
  executables: []
170
170
  extensions:
@@ -245,7 +245,7 @@ metadata:
245
245
  homepage_uri: https://github.com/Lykos/twisty_puzzles
246
246
  source_code_uri: https://github.com/Lykos/twisty_puzzles
247
247
  changelog_uri: https://github.com/Lykos/twisty_puzzles/blob/master/CHANGELOG.md
248
- post_install_message:
248
+ post_install_message:
249
249
  rdoc_options: []
250
250
  require_paths:
251
251
  - lib
@@ -253,16 +253,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
253
253
  requirements:
254
254
  - - ">="
255
255
  - !ruby/object:Gem::Version
256
- version: 2.3.0
256
+ version: 3.0.0
257
257
  required_rubygems_version: !ruby/object:Gem::Requirement
258
258
  requirements:
259
259
  - - ">="
260
260
  - !ruby/object:Gem::Version
261
261
  version: '0'
262
262
  requirements: []
263
- rubyforge_project:
264
- rubygems_version: 2.7.6.2
265
- signing_key:
263
+ rubygems_version: 3.2.3
264
+ signing_key:
266
265
  specification_version: 4
267
266
  summary: Gem for my cube_trainer rails app. Some things are better left in a separate
268
267
  gem with no rails, e.g. native extensions. The main purpose is to support my Rails