twisty_puzzles 0.0.1 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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