snake cube solver
by dp0ch
HTML
<html>
<head>
<script src="https://cdn.plot.ly/plotly-1.40.1.min.js"></script>
</head>
<body>
<div id="graph"></div>
</body>
</html>
CSS
body, html, #graph{
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
Babel + JSX
const cube = [3, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 1, 2, 1, 1, 2];
(async () => {
const solution = await solveCube(cube);
console.log(solution);
render(solution);
})()
/// SOLVER ///
function solveCube(cubeSequence) {
let moves = 0;
const cubeDimension = Math.cbrt(cubeSequence.reduce((acc, n) => n + acc, 0));
if (!Number.isInteger(cubeDimension)) throw new Error('Invalid/unsolvable cube sequence');
const [firstSegment, ...restSequence] = cubeSequence;
if (firstSegment > cubeDimension || firstSegment < 2) throw new Error('Invalid/unsolvable cube sequence');
const solution = solve([firstSegment - 1, ...restSequence]);
if (!solution) throw new Error('Invalid/unsolvable cube sequence');
return solution;
async function solve(
cubeSequence,
{
direction = {x: 0, y: 0, z: 0},
position = {x: 0, y: 0, z: 0},
cellOccupation = {[[0, 0, 0]]: true},
bounds = {
lower: {x: 0, y: 0, z: 0},
upper: {x: 0, y: 0, z: 0},
},
} = {}
) {
if (cubeSequence.length <= 0) return [position];
const [segment, ...restSequence] = cubeSequence;
for(const moveDirection of orthogonals(direction, segment)) {
const move = getMove(moveDirection, {position, cellOccupation, bounds});
console.log(++moves);
if (!move) continue;
const solution = await new Promise((resolve) => {
setTimeout(async () => {
resolve(await solve(restSequence, move));
}, 0);
});
if (solution) return [position, ...solution];
}
}
function getMove(direction, {position, cellOccupation, bounds}) {
const nextPosition = vec3Add(position, direction);
const nextBounds = extendBounds(bounds, nextPosition);
if (!nextBounds) return null;
const nextCells = extendCellOccupation(cellOccupation, position, nextPosition);
if (!nextCells) return null;
return {
direction,
position: nextPosition,
bounds: nextBounds,
cellOccupation:...