twisty_puzzles 0.0.1 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -1
  3. data/README.md +6 -1
  4. data/ext/twisty_puzzles/native/cube_algorithm.c +267 -0
  5. data/ext/twisty_puzzles/native/cube_algorithm.h +5 -0
  6. data/ext/twisty_puzzles/native/cube_average.c +184 -0
  7. data/ext/twisty_puzzles/native/cube_average.h +5 -0
  8. data/ext/twisty_puzzles/native/cube_coordinate.c +207 -0
  9. data/ext/twisty_puzzles/native/cube_coordinate.h +34 -0
  10. data/ext/twisty_puzzles/native/cube_state.c +264 -0
  11. data/ext/twisty_puzzles/native/cube_state.h +31 -0
  12. data/ext/twisty_puzzles/native/extconf.rb +1 -1
  13. data/ext/twisty_puzzles/native/face_symbols.c +67 -0
  14. data/ext/twisty_puzzles/native/face_symbols.h +34 -0
  15. data/ext/twisty_puzzles/native/native.c +28 -0
  16. data/ext/twisty_puzzles/native/skewb_algorithm.c +331 -0
  17. data/ext/twisty_puzzles/native/skewb_algorithm.h +5 -0
  18. data/ext/twisty_puzzles/native/skewb_coordinate.c +237 -0
  19. data/ext/twisty_puzzles/native/skewb_coordinate.h +36 -0
  20. data/ext/twisty_puzzles/native/skewb_layer_fingerprint.c +271 -0
  21. data/ext/twisty_puzzles/native/skewb_layer_fingerprint.h +5 -0
  22. data/ext/twisty_puzzles/native/skewb_state.c +214 -0
  23. data/ext/twisty_puzzles/native/skewb_state.h +23 -0
  24. data/ext/twisty_puzzles/native/utils.c +76 -0
  25. data/ext/twisty_puzzles/native/utils.h +31 -0
  26. data/lib/twisty_puzzles.rb +38 -0
  27. data/lib/twisty_puzzles/abstract_direction.rb +38 -39
  28. data/lib/twisty_puzzles/abstract_move.rb +1 -2
  29. data/lib/twisty_puzzles/abstract_move_parser.rb +32 -33
  30. data/lib/twisty_puzzles/algorithm.rb +112 -113
  31. data/lib/twisty_puzzles/algorithm_transformation.rb +19 -21
  32. data/lib/twisty_puzzles/axis_face_and_direction_move.rb +56 -56
  33. data/lib/twisty_puzzles/cancellation_helper.rb +124 -125
  34. data/lib/twisty_puzzles/color_scheme.rb +1 -1
  35. data/lib/twisty_puzzles/commutator.rb +82 -80
  36. data/lib/twisty_puzzles/compiled_algorithm.rb +31 -32
  37. data/lib/twisty_puzzles/compiled_cube_algorithm.rb +49 -50
  38. data/lib/twisty_puzzles/compiled_skewb_algorithm.rb +18 -19
  39. data/lib/twisty_puzzles/coordinate.rb +243 -246
  40. data/lib/twisty_puzzles/cube.rb +494 -495
  41. data/lib/twisty_puzzles/cube_constants.rb +40 -41
  42. data/lib/twisty_puzzles/cube_direction.rb +15 -18
  43. data/lib/twisty_puzzles/cube_move.rb +285 -290
  44. data/lib/twisty_puzzles/cube_move_parser.rb +75 -76
  45. data/lib/twisty_puzzles/cube_print_helper.rb +133 -133
  46. data/lib/twisty_puzzles/cube_state.rb +80 -81
  47. data/lib/twisty_puzzles/move_type_creator.rb +17 -18
  48. data/lib/twisty_puzzles/parser.rb +176 -179
  49. data/lib/twisty_puzzles/part_cycle_factory.rb +39 -42
  50. data/lib/twisty_puzzles/puzzle.rb +16 -17
  51. data/lib/twisty_puzzles/reversible_applyable.rb +24 -25
  52. data/lib/twisty_puzzles/rotation.rb +76 -75
  53. data/lib/twisty_puzzles/skewb_direction.rb +14 -15
  54. data/lib/twisty_puzzles/skewb_move.rb +49 -49
  55. data/lib/twisty_puzzles/skewb_move_parser.rb +51 -51
  56. data/lib/twisty_puzzles/skewb_notation.rb +121 -118
  57. data/lib/twisty_puzzles/skewb_state.rb +120 -121
  58. data/lib/twisty_puzzles/state_helper.rb +20 -21
  59. data/lib/twisty_puzzles/sticker_cycle.rb +43 -44
  60. data/lib/twisty_puzzles/utils.rb +3 -0
  61. data/lib/twisty_puzzles/version.rb +3 -1
  62. metadata +30 -10
@@ -10,91 +10,90 @@ require 'twisty_puzzles/rotation'
10
10
  require 'twisty_puzzles/skewb_move'
11
11
 
12
12
  module TwistyPuzzles
13
-
14
- # Parser for cube moves.
15
- class CubeMoveParser < AbstractMoveParser
16
- REGEXP =
17
- begin
18
- axes_part = "(?<axis_name>[#{AbstractMove::AXES.join}])"
19
- face_names = CubeConstants::FACE_NAMES.join
20
- fat_move_part =
21
- "(?<width>\\d*)(?<fat_face_name>[#{face_names}])w"
22
- normal_move_part = "(?<face_name>[#{face_names}])"
23
- downcased_face_names = face_names.downcase
24
- maybe_fat_maybe_slice_move_part =
25
- "(?<maybe_fat_face_maybe_slice_name>[#{downcased_face_names}])"
26
- slice_move_part =
27
- "(?<slice_index>\\d+)(?<slice_name>[#{downcased_face_names}])"
28
- mslice_move_part =
29
- "(?<mslice_name>[#{AbstractMove::SLICE_FACES.keys.join}])"
30
- move_part = "(?:#{axes_part}|" \
31
- "#{fat_move_part}|" \
32
- "#{normal_move_part}|" \
33
- "#{maybe_fat_maybe_slice_move_part}|" \
34
- "#{slice_move_part}|#{mslice_move_part})"
35
- direction_names =
36
- AbstractDirection::POSSIBLE_DIRECTION_NAMES.flatten
37
- direction_names.sort_by! { |e| -e.length }
38
- direction_part = "(?<direction>#{direction_names.join('|')})"
39
- Regexp.new("#{move_part}#{direction_part}")
40
- end
13
+ # Parser for cube moves.
14
+ class CubeMoveParser < AbstractMoveParser
15
+ REGEXP =
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
41
40
 
42
- MOVE_TYPE_CREATORS = [
43
- MoveTypeCreator.new(%i[axis_face direction], Rotation),
44
- MoveTypeCreator.new(%i[fat_face direction width], FatMove),
45
- MoveTypeCreator.new(%i[face direction], FatMove),
46
- MoveTypeCreator.new(%i[maybe_fat_face_maybe_slice_face direction], MaybeFatMaybeSliceMove),
47
- MoveTypeCreator.new(%i[slice_face direction slice_index], SliceMove),
48
- MoveTypeCreator.new(%i[mslice_face direction], MaybeFatMSliceMaybeInnerMSliceMove)
49
- ].freeze
41
+ MOVE_TYPE_CREATORS = [
42
+ MoveTypeCreator.new(%i[axis_face direction], Rotation),
43
+ MoveTypeCreator.new(%i[fat_face direction width], FatMove),
44
+ MoveTypeCreator.new(%i[face direction], FatMove),
45
+ MoveTypeCreator.new(%i[maybe_fat_face_maybe_slice_face direction], MaybeFatMaybeSliceMove),
46
+ MoveTypeCreator.new(%i[slice_face direction slice_index], SliceMove),
47
+ MoveTypeCreator.new(%i[mslice_face direction], MaybeFatMSliceMaybeInnerMSliceMove)
48
+ ].freeze
50
49
 
51
- INSTANCE = CubeMoveParser.new
52
- def regexp
53
- REGEXP
54
- end
50
+ INSTANCE = CubeMoveParser.new
51
+ def regexp
52
+ REGEXP
53
+ end
55
54
 
56
- def move_type_creators
57
- MOVE_TYPE_CREATORS
58
- end
55
+ def move_type_creators
56
+ MOVE_TYPE_CREATORS
57
+ end
59
58
 
60
- def parse_part_key(name)
61
- name.sub('_name', '_face').sub('face_face', 'face')
62
- end
59
+ def parse_part_key(name)
60
+ name.sub('_name', '_face').sub('face_face', 'face')
61
+ end
63
62
 
64
- def parse_direction(direction_string)
65
- value = AbstractDirection::POSSIBLE_DIRECTION_NAMES.index do |ds|
66
- ds.include?(direction_string)
67
- end + 1
68
- CubeDirection.new(value)
69
- end
63
+ def parse_direction(direction_string)
64
+ value = AbstractDirection::POSSIBLE_DIRECTION_NAMES.index do |ds|
65
+ ds.include?(direction_string)
66
+ end + 1
67
+ CubeDirection.new(value)
68
+ end
70
69
 
71
- def parse_axis_face(axis_face_string)
72
- Face::ELEMENTS[AbstractMove::AXES.index(axis_face_string)]
73
- end
70
+ def parse_axis_face(axis_face_string)
71
+ Face::ELEMENTS[AbstractMove::AXES.index(axis_face_string)]
72
+ end
74
73
 
75
- def parse_mslice_face(mslice_name)
76
- AbstractMove::SLICE_FACES[mslice_name]
77
- end
74
+ def parse_mslice_face(mslice_name)
75
+ AbstractMove::SLICE_FACES[mslice_name]
76
+ end
78
77
 
79
- def parse_width(width_string)
80
- width_string.empty? ? 2 : Integer(width_string, 10)
81
- end
78
+ def parse_width(width_string)
79
+ width_string.empty? ? 2 : Integer(width_string, 10)
80
+ end
82
81
 
83
- # rubocop:disable Metrics/CyclomaticComplexity
84
- def parse_move_part(name, value)
85
- case name
86
- when 'axis_name' then parse_axis_face(value)
87
- when 'width' then parse_width(value)
88
- when 'slice_index' then Integer(value, 10)
89
- when 'fat_face_name', 'face_name' then Face.by_name(value)
90
- when 'maybe_fat_face_maybe_slice_name', 'slice_name'
91
- Face.by_name(value.upcase)
92
- when 'mslice_name'
93
- parse_mslice_face(value)
94
- when 'direction' then parse_direction(value)
95
- else raise
96
- end
82
+ # rubocop:disable Metrics/CyclomaticComplexity
83
+ def parse_move_part(name, value)
84
+ case name
85
+ when 'axis_name' then parse_axis_face(value)
86
+ when 'width' then parse_width(value)
87
+ when 'slice_index' then Integer(value, 10)
88
+ when 'fat_face_name', 'face_name' then Face.by_name(value)
89
+ when 'maybe_fat_face_maybe_slice_name', 'slice_name'
90
+ Face.by_name(value.upcase)
91
+ when 'mslice_name'
92
+ parse_mslice_face(value)
93
+ when 'direction' then parse_direction(value)
94
+ else raise
97
95
  end
98
- # rubocop:enable Metrics/CyclomaticComplexity
99
96
  end
97
+ # rubocop:enable Metrics/CyclomaticComplexity
98
+ end
100
99
  end
@@ -4,157 +4,157 @@ require 'colorize'
4
4
  require 'twisty_puzzles/utils/array_helper'
5
5
 
6
6
  module TwistyPuzzles
7
-
8
- # Module to print and display cube and Skewb states.
9
- module CubePrintHelper
10
- include Utils::ArrayHelper
11
-
12
- def color_symbol(color)
13
- case color
14
- when :orange then :light_red
15
- when :unknown then :light_black
16
- else color
17
- end
7
+ # Module to print and display cube and Skewb states.
8
+ module CubePrintHelper
9
+ include Utils::ArrayHelper
10
+
11
+ def color_symbol(color)
12
+ case color
13
+ when :orange then :light_red
14
+ when :unknown then :light_black
15
+ else color
18
16
  end
17
+ end
19
18
 
20
- COLOR_MODES = %i[color nocolor].freeze
21
- ColorInfo = Struct.new(:reverse_lines_mode, :reverse_columns_mode, :skewb_corner_permutation)
22
- FACE_SYMBOL_INFOS = {
23
- U: ColorInfo.new(:reverse, :reverse, [2, 3, 0, 1]),
24
- L: ColorInfo.new(:keep, :reverse, [2, 0, 3, 1]),
25
- F: ColorInfo.new(:keep, :reverse, [2, 0, 3, 1]),
26
- R: ColorInfo.new(:keep, :keep, [1, 0, 3, 2]),
27
- B: ColorInfo.new(:keep, :keep, [1, 0, 3, 2]),
28
- D: ColorInfo.new(:keep, :reverse, [2, 0, 3, 1])
29
- }.freeze
30
-
31
- def color_character(color, color_mode)
32
- unless COLOR_MODES.include?(color_mode)
33
- raise ArgumentError, "Invalid color mode #{color_mode}"
34
- end
35
-
36
- char = color.to_s[0].upcase
37
- if color_mode == :color
38
- char.colorize(background: color_symbol(color))
39
- else
40
- char
41
- end
19
+ COLOR_MODES = %i[color nocolor].freeze
20
+ ColorInfo = Struct.new(:reverse_lines_mode, :reverse_columns_mode, :skewb_corner_permutation)
21
+ FACE_SYMBOL_INFOS = {
22
+ U: ColorInfo.new(:reverse, :reverse, [2, 3, 0, 1]),
23
+ L: ColorInfo.new(:keep, :reverse, [2, 0, 3, 1]),
24
+ F: ColorInfo.new(:keep, :reverse, [2, 0, 3, 1]),
25
+ R: ColorInfo.new(:keep, :keep, [1, 0, 3, 2]),
26
+ B: ColorInfo.new(:keep, :keep, [1, 0, 3, 2]),
27
+ D: ColorInfo.new(:keep, :reverse, [2, 0, 3, 1])
28
+ }.freeze
29
+
30
+ def color_character(color, color_mode)
31
+ unless COLOR_MODES.include?(color_mode)
32
+ raise ArgumentError, "Invalid color mode #{color_mode}"
42
33
  end
43
34
 
44
- def maybe_reverse(reverse_mode, stuff)
45
- if reverse_mode == :reverse
46
- stuff.reverse
47
- elsif reverse_mode == :keep
48
- stuff
49
- else
50
- raise
51
- end
35
+ char = color.to_s[0].upcase
36
+ if color_mode == :color
37
+ char.colorize(background: color_symbol(color))
38
+ else
39
+ char
52
40
  end
41
+ end
53
42
 
54
- def face_lines(cube_state, face_symbol, row_multiplicity = 1, column_multiplicity = 1)
55
- face = Face.for_face_symbol(face_symbol)
56
- face_symbol_info = FACE_SYMBOL_INFOS[face_symbol]
57
- stickers = cube_state.sticker_array(face)
58
- lines =
59
- stickers.collect_concat do |sticker_line|
60
- line = sticker_line.map { |c| yield(c) * column_multiplicity }
61
- [maybe_reverse(face_symbol_info.reverse_columns_mode, line).join] * row_multiplicity
62
- end
63
- maybe_reverse(face_symbol_info.reverse_lines_mode, lines)
43
+ def maybe_reverse(reverse_mode, stuff)
44
+ case reverse_mode
45
+ when :reverse
46
+ stuff.reverse
47
+ when :keep
48
+ stuff
49
+ else
50
+ raise
64
51
  end
52
+ end
65
53
 
66
- def simple_face_lines(cube_state, face_symbol, color_mode)
67
- face_lines(cube_state, face_symbol) { |c| color_character(c, color_mode) }
68
- end
54
+ def face_lines(cube_state, face_symbol, row_multiplicity = 1, column_multiplicity = 1)
55
+ face = Face.for_face_symbol(face_symbol)
56
+ face_symbol_info = FACE_SYMBOL_INFOS[face_symbol]
57
+ stickers = cube_state.sticker_array(face)
58
+ lines =
59
+ stickers.collect_concat do |sticker_line|
60
+ line = sticker_line.map { |c| yield(c) * column_multiplicity }
61
+ [maybe_reverse(face_symbol_info.reverse_columns_mode, line).join] * row_multiplicity
62
+ end
63
+ maybe_reverse(face_symbol_info.reverse_lines_mode, lines)
64
+ end
69
65
 
70
- SKEWB_FACE_SIZE = 5
66
+ def simple_face_lines(cube_state, face_symbol, color_mode)
67
+ face_lines(cube_state, face_symbol) { |c| color_character(c, color_mode) }
68
+ end
71
69
 
72
- def skewb_ascii_art_line(first_color, middle_color, last_color, num_first_color)
73
- raise if num_first_color > SKEWB_FACE_SIZE / 2
70
+ SKEWB_FACE_SIZE = 5
74
71
 
75
- first_color * num_first_color +
76
- middle_color * (SKEWB_FACE_SIZE - 2 * num_first_color) +
77
- last_color * num_first_color
78
- end
72
+ def skewb_ascii_art_line(first_color, middle_color, last_color, num_first_color)
73
+ raise if num_first_color > SKEWB_FACE_SIZE / 2
79
74
 
80
- def skewb_ascii_art(center_color, corner_colors)
81
- raise unless corner_colors.length == 4
82
-
83
- first_part =
84
- (1..SKEWB_FACE_SIZE / 2).to_a.reverse.map do |i|
85
- skewb_ascii_art_line(corner_colors[0], center_color, corner_colors[1], i)
86
- end
87
- middle_part = SKEWB_FACE_SIZE.odd? ? [center_color * SKEWB_FACE_SIZE] : []
88
- last_part =
89
- (1..SKEWB_FACE_SIZE / 2).map do |i|
90
- skewb_ascii_art_line(corner_colors[2], center_color, corner_colors[3], i)
91
- end
92
- first_part + middle_part + last_part
93
- end
75
+ first_color * num_first_color +
76
+ middle_color * (SKEWB_FACE_SIZE - 2 * num_first_color) +
77
+ last_color * num_first_color
78
+ end
94
79
 
95
- # Prints a Skewb face like this:
96
- # rrgww
97
- # rgggw
98
- # ggggg
99
- # ogggb
100
- # oogbb
101
- def skewb_face_lines(cube_state, face_symbol, color_mode)
102
- face = Face.for_face_symbol(face_symbol)
103
- face_symbol_info = FACE_SYMBOL_INFOS[face_symbol]
104
- stickers = cube_state.sticker_array(face)
105
- center_color = color_character(stickers[0], color_mode)
106
- corner_colors = stickers[1..-1].map { |c| color_character(c, color_mode) }
107
- permuted_corner_colors =
108
- apply_permutation(corner_colors, face_symbol_info.skewb_corner_permutation)
109
- raise unless corner_colors.length == 4
110
-
111
- skewb_ascii_art(center_color, permuted_corner_colors)
112
- end
80
+ def skewb_ascii_art(center_color, corner_colors)
81
+ raise unless corner_colors.length == 4
113
82
 
114
- def ll_string(cube_state, color_mode)
115
- top_face = face_lines(cube_state, :U, 2, 3) { |c| color_character(c, color_mode) }
116
- front_face = face_lines(cube_state, :F, 1, 3) { |c| color_character(c, color_mode) }
117
- right_face = face_lines(cube_state, :R, 1, 3) { |c| color_character(c, color_mode) }
118
- pll_line = front_face.first + right_face.first
119
- (top_face + [pll_line] * 3).join("\n")
120
- end
83
+ first_part =
84
+ (1..SKEWB_FACE_SIZE / 2).to_a.reverse.map do |i|
85
+ skewb_ascii_art_line(corner_colors[0], center_color, corner_colors[1], i)
86
+ end
87
+ middle_part = SKEWB_FACE_SIZE.odd? ? [center_color * SKEWB_FACE_SIZE] : []
88
+ last_part =
89
+ (1..SKEWB_FACE_SIZE / 2).map do |i|
90
+ skewb_ascii_art_line(corner_colors[2], center_color, corner_colors[3], i)
91
+ end
92
+ first_part + middle_part + last_part
93
+ end
121
94
 
122
- def cube_string(cube_state, color_mode)
123
- top_face = simple_face_lines(cube_state, :U, color_mode)
124
- left_face = simple_face_lines(cube_state, :L, color_mode)
125
- front_face = simple_face_lines(cube_state, :F, color_mode)
126
- right_face = simple_face_lines(cube_state, :R, color_mode)
127
- back_face = simple_face_lines(cube_state, :B, color_mode)
128
- bottom_face = simple_face_lines(cube_state, :D, color_mode)
129
- middle_belt = zip_concat_lines(left_face, front_face, right_face, back_face)
130
- lines = pad_lines(top_face, cube_state.n) + middle_belt +
131
- pad_lines(bottom_face, cube_state.n)
132
- lines.join("\n")
133
- end
95
+ # Prints a Skewb face like this:
96
+ # rrgww
97
+ # rgggw
98
+ # ggggg
99
+ # ogggb
100
+ # oogbb
101
+ def skewb_face_lines(cube_state, face_symbol, color_mode)
102
+ face = Face.for_face_symbol(face_symbol)
103
+ face_symbol_info = FACE_SYMBOL_INFOS[face_symbol]
104
+ stickers = cube_state.sticker_array(face)
105
+ center_color = color_character(stickers[0], color_mode)
106
+ corner_colors = stickers[1..].map { |c| color_character(c, color_mode) }
107
+ permuted_corner_colors =
108
+ apply_permutation(corner_colors, face_symbol_info.skewb_corner_permutation)
109
+ raise unless corner_colors.length == 4
110
+
111
+ skewb_ascii_art(center_color, permuted_corner_colors)
112
+ end
134
113
 
135
- def skewb_string(skewb_state, color_mode)
136
- top_face = skewb_face_lines(skewb_state, :U, color_mode)
137
- left_face = skewb_face_lines(skewb_state, :L, color_mode)
138
- front_face = skewb_face_lines(skewb_state, :F, color_mode)
139
- right_face = skewb_face_lines(skewb_state, :R, color_mode)
140
- back_face = skewb_face_lines(skewb_state, :B, color_mode)
141
- bottom_face = skewb_face_lines(skewb_state, :D, color_mode)
142
- middle_belt = zip_concat_lines(left_face, front_face, right_face, back_face)
143
- lines = pad_lines(top_face, SKEWB_FACE_SIZE) + middle_belt +
144
- pad_lines(bottom_face, SKEWB_FACE_SIZE)
145
- lines.join("\n")
146
- end
114
+ def ll_string(cube_state, color_mode)
115
+ top_face = face_lines(cube_state, :U, 2, 3) { |c| color_character(c, color_mode) }
116
+ front_face = face_lines(cube_state, :F, 1, 3) { |c| color_character(c, color_mode) }
117
+ right_face = face_lines(cube_state, :R, 1, 3) { |c| color_character(c, color_mode) }
118
+ pll_line = front_face.first + right_face.first
119
+ (top_face + [pll_line] * 3).join("\n")
120
+ end
147
121
 
148
- def empty_name
149
- ' '
150
- end
122
+ def cube_string(cube_state, color_mode)
123
+ top_face = simple_face_lines(cube_state, :U, color_mode)
124
+ left_face = simple_face_lines(cube_state, :L, color_mode)
125
+ front_face = simple_face_lines(cube_state, :F, color_mode)
126
+ right_face = simple_face_lines(cube_state, :R, color_mode)
127
+ back_face = simple_face_lines(cube_state, :B, color_mode)
128
+ bottom_face = simple_face_lines(cube_state, :D, color_mode)
129
+ middle_belt = zip_concat_lines(left_face, front_face, right_face, back_face)
130
+ lines = pad_lines(top_face, cube_state.n) + middle_belt +
131
+ pad_lines(bottom_face, cube_state.n)
132
+ lines.join("\n")
133
+ end
151
134
 
152
- def pad_lines(lines, padding)
153
- lines.map { |line| empty_name * padding + line }
154
- end
135
+ def skewb_string(skewb_state, color_mode)
136
+ top_face = skewb_face_lines(skewb_state, :U, color_mode)
137
+ left_face = skewb_face_lines(skewb_state, :L, color_mode)
138
+ front_face = skewb_face_lines(skewb_state, :F, color_mode)
139
+ right_face = skewb_face_lines(skewb_state, :R, color_mode)
140
+ back_face = skewb_face_lines(skewb_state, :B, color_mode)
141
+ bottom_face = skewb_face_lines(skewb_state, :D, color_mode)
142
+ middle_belt = zip_concat_lines(left_face, front_face, right_face, back_face)
143
+ lines = pad_lines(top_face, SKEWB_FACE_SIZE) + middle_belt +
144
+ pad_lines(bottom_face, SKEWB_FACE_SIZE)
145
+ lines.join("\n")
146
+ end
155
147
 
156
- def zip_concat_lines(*args)
157
- args.transpose.map(&:join)
158
- end
148
+ def empty_name
149
+ ' '
150
+ end
151
+
152
+ def pad_lines(lines, padding)
153
+ lines.map { |line| empty_name * padding + line }
154
+ end
155
+
156
+ def zip_concat_lines(*args)
157
+ args.transpose.map(&:join)
159
158
  end
159
+ end
160
160
  end