Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions lib/rubiks_cube/sticker_state_transform.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,37 @@ class StickerStateTransform
46, 7 , 50, 16, 52, 25, 48, 34
]

LOCATION_COUNT = 54

def initialize(state)
@state = state.gsub(/\s/, '').split('')
if @state.length < LOCATION_COUNT
raise 'too few stickers'
elsif @state.length > LOCATION_COUNT
raise 'too many stickers'
end
end

def to_cube
(edges + corners).join(' ').gsub(/./) { |c| color_mapping.fetch(c, c) }
(edges + corners).join(' ').gsub(/./) { |c| map_color(c) }
end

private

def map_color(color)
return ' ' if color == ' '
@color_mapping ||= color_mapping
@color_mapping[color] or
raise "#{color} is not listed in the center anywhere"
end

def color_mapping
Hash[state.values_at(*CENTER_LOCATIONS).zip %w(F R B L U D)]
center_values = state.values_at(*CENTER_LOCATIONS)
dup = center_values.detect do |e|
center_values.rindex(e) != center_values.index(e)
end
raise "#{dup} is listed in the center twice" if dup
Hash[center_values.zip %w(F R B L U D)]
end

def edges
Expand Down
11 changes: 9 additions & 2 deletions spec/rubiks_cube/cube_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,15 @@
end

describe '#state=' do
it 'changes the state of the cube' do
expect { subject.state = 'a b c' }.to change { subject.state }
it 'expects a sticker-style state' do
expect { subject.state = <<-STATE }.to change { subject.state }
R G O R G O O W G
G W W B Y W Y Y Y
G B B G B W R Y B
Y G Y B W G R Y W
O R R O R O G Y W
B R O R O O W B B
STATE
end
end

Expand Down
72 changes: 72 additions & 0 deletions spec/rubiks_cube/sticker_state_transform_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,77 @@
)
end
end

context "for a solved cube" do
let(:state) { <<-STATE }
BBB BBB BBB WWW WWW WWW RRR RRR RRR YYY YYY YYY OOO OOO OOO GGG GGG GGG
STATE

it 'transforms to cube state' do
expect(subject.to_cube).to eq(
"UF UR UB UL FL FR BR BL DF DR DB DL UFL URF UBR ULB DLF DFR DRB DBL"
)
end
end

context 'for an example with a few scrambled faces' do
let(:state) { <<-STATE }
GGY GGR GGG RRY YYY YYY WWW WWW WWB BBB BBB OBB RRR RRG RYG OOO OOO WOO
STATE

it 'transforms to cube state' do
expect(subject.to_cube).to eq(
"RF FU UB UL FL UR BR BL DF DR DB DL UFL FUR UBR ULB DLF DFR DRB BLD"
)
end
end

context 'with too few letters' do
let(:state) {
'GGY GGR GGG RRY YYY YYY WW WWW WWB BBB BBB OBB RRR RRG RYG OOO OOO WOO'
}

it 'throws an exception' do
expect {
subject.to_cube
}.to raise_error('too few stickers')
end
end

context 'with too many letters' do
let(:state) { <<-STATE }
GGY GGR GGG RRY YYY YYY WWWW WWW WWB BBB BBB OBB RRR RRG RYG OOO OOO WOO
STATE

it 'throws an exception' do
expect {
subject.to_cube
}.to raise_error('too many stickers')
end
end

context 'two center faces are identical' do
let(:state) { <<-STATE }
BBB BBB BBB WWW WBW WWW RRR RRR RRR YYY YYY YYY OOO OOO OOO GGG GGG GGG
STATE

it 'throws an exception' do
expect {
subject.to_cube
}.to raise_error('B is listed in the center twice')
end
end

context 'with a color not in a center face' do
let(:state) { <<-STATE }
PBB BBB BBB WWW WWW WWW RRR RRR RRR YYY YYY YYY OOO OOO OOO GGG GGG GGG
STATE

it 'throws an exception' do
expect {
subject.to_cube
}.to raise_error('P is not listed in the center anywhere')
end
end
end
end