Last active
December 26, 2017 00:59
-
-
Save itarato/49c6fc99e498f24e2885c186575b150d to your computer and use it in GitHub Desktop.
Rubik cube algorithm seeker.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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