Create a gist now

Instantly share code, notes, and snippets.

@itarato /rubik.rb
Last active Dec 26, 2017

Embed
Rubik cube algorithm seeker.
require 'pp'
class Cube
attr_accessor :cells
def initialize
@cells = {
top: [0] * 9,
front: [1] * 9,
left: [2] * 9,
right: [3] * 9,
bottom: [4] * 9,
back: [5] * 9,
}
end
def rot(side)
rot_side(side)
case side
when :front
rot_perim(top: [6, 7, 8], right: [0, 3, 6], bottom: [6, 7, 8], left: [8, 5, 2])
when :top
rot_perim(back: [2, 1, 0], right: [2, 1, 0], front: [2, 1, 0], left: [2, 1, 0])
when :right
rot_perim(top: [8, 5, 2], back: [0, 3, 6], bottom: [0, 3, 6], front: [2, 5, 8])
when :left
rot_perim(top: [0, 3, 6], front: [0, 3, 6], bottom: [8, 5, 2], back: [8, 5, 2])
when :back
rot_perim(top: [2, 1, 0], left: [0, 3, 6], bottom: [2, 1, 0], right: [8, 5, 2])
when :bottom
rot_perim(back: [6, 7, 8], left: [6, 7, 8], front: [6, 7, 8], right: [6, 7, 8])
end
end
private
def clone_cell
Marshal.load(Marshal.dump(@cells))
end
def rot_side(side)
old = clone_cell
@cells[side][0] = old[side][6]
@cells[side][1] = old[side][3]
@cells[side][2] = old[side][0]
@cells[side][3] = old[side][7]
@cells[side][5] = old[side][1]
@cells[side][6] = old[side][8]
@cells[side][7] = old[side][5]
@cells[side][8] = old[side][2]
end
def rot_perim(**list)
old = clone_cell
4.times do |side_idx|
3.times do |cell_idx|
@cells[list.to_a[(side_idx + 1) % 4][0]][list.to_a[(side_idx + 1) % 4][1][cell_idx]] = old[list.to_a[side_idx][0]][list.to_a[side_idx][1][cell_idx]]
end
end
end
end
class SolutionFinder
SIDES = [:front, :top, :left, :right, :back, :bottom]
MAX_TRY = 20
SUCCESS_DISTANCE = 4
def initialize
@cube = Cube.new
@cube_reference = Cube.new
@cube_reference.freeze
end
def seek
while true
@cube = Cube.new
steps = []
MAX_TRY.times do |n|
side = SIDES.sample
dir = [1, 3].sample
steps << [side, dir]
dir.times { @cube.rot(side) }
dist = distance
if dist > 0 && dist <= SUCCESS_DISTANCE
puts "Potential algorithm in #{n} steps with distance #{dist}"
pp steps
HTMLPrinter.print(@cube.cells, steps, dist)
break
end
end
end
end
def distance
d = 0
@cube_reference.cells.each do |side, cells|
cells.each_with_index { |cell, idx| d += 1 if cell != @cube.cells[side][idx] }
end
d
end
end
class HTMLPrinter
class << self
def print(cells, steps, distance)
initialize_file_if_necessary
File.open(filename, 'a') do |f|
f.puts <<~HTML
<div class="cube">
<div class="half h1">
<div class="side s1">
<div class="row r1">
<div class="cell c1" style="background-color:#{colors[cells[:top][0]]}"></div>
<div class="cell c2" style="background-color:#{colors[cells[:top][1]]}"></div>
<div class="cell c3" style="background-color:#{colors[cells[:top][2]]}"></div>
<div style="clear: both"></div>
</div>
<div class="row r2">
<div class="cell c1" style="background-color:#{colors[cells[:top][3]]}"></div>
<div class="cell c2" style="background-color:#{colors[cells[:top][4]]}"></div>
<div class="cell c3" style="background-color:#{colors[cells[:top][5]]}"></div>
<div style="clear: both"></div>
</div>
<div class="row r3">
<div class="cell c1" style="background-color:#{colors[cells[:top][6]]}"></div>
<div class="cell c2" style="background-color:#{colors[cells[:top][7]]}"></div>
<div class="cell c3" style="background-color:#{colors[cells[:top][8]]}"></div>
<div style="clear: both"></div>
</div>
</div>
<div class="side s2">
<div class="row r1">
<div class="cell c1" style="background-color:#{colors[cells[:front][0]]}"></div>
<div class="cell c2" style="background-color:#{colors[cells[:front][1]]}"></div>
<div class="cell c3" style="background-color:#{colors[cells[:front][2]]}"></div>
<div style="clear: both"></div>
</div>
<div class="row r2">
<div class="cell c1" style="background-color:#{colors[cells[:front][3]]}"></div>
<div class="cell c2" style="background-color:#{colors[cells[:front][4]]}"></div>
<div class="cell c3" style="background-color:#{colors[cells[:front][5]]}"></div>
<div style="clear: both"></div>
</div>
<div class="row r3">
<div class="cell c1" style="background-color:#{colors[cells[:front][6]]}"></div>
<div class="cell c2" style="background-color:#{colors[cells[:front][7]]}"></div>
<div class="cell c3" style="background-color:#{colors[cells[:front][8]]}"></div>
<div style="clear: both"></div>
</div>
</div>
<div class="side s3">
<div class="row r1">
<div class="cell c1" style="background-color:#{colors[cells[:right][0]]}"></div>
<div class="cell c2" style="background-color:#{colors[cells[:right][1]]}"></div>
<div class="cell c3" style="background-color:#{colors[cells[:right][2]]}"></div>
<div style="clear: both"></div>
</div>
<div class="row r2">
<div class="cell c1" style="background-color:#{colors[cells[:right][3]]}"></div>
<div class="cell c2" style="background-color:#{colors[cells[:right][4]]}"></div>
<div class="cell c3" style="background-color:#{colors[cells[:right][5]]}"></div>
<div style="clear: both"></div>
</div>
<div class="row r3">
<div class="cell c1" style="background-color:#{colors[cells[:right][6]]}"></div>
<div class="cell c2" style="background-color:#{colors[cells[:right][7]]}"></div>
<div class="cell c3" style="background-color:#{colors[cells[:right][8]]}"></div>
<div style="clear: both"></div>
</div>
</div>
</div>
</div>
HTML
end
end
def colors
[
'lightgrey',
'red',
'green',
'blue',
'yellow',
'orange',
]
end
def initialize_file_if_necessary
return if File.exist?(filename)
File.open(filename, 'w') do |f|
f.puts <<~HEAD
<style>
.side {
width: 186px;
}
.cell {
width: 60px;
height: 60px;
}
.row .cell {
float: left;
margin: 1px;
}
.side.s1 {
transform: skewX(-45deg) translate(48px, 0px);
}
.side.s3 {
transform: skewY(-45deg) translate(186px, -92px);
}
.side.s1 .cell {
height: 30px;
}
.side.s3 .cell {
width: 30px;
}
</style>
HEAD
end
end
def filename
@filename ||= "/home/itarato/Desktop/rubik_result_#{Time.now.to_i}.html"
end
end
end
SolutionFinder.new.seek
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment