great stuff

This commit is contained in:
Daniel Ledda
2021-06-08 17:29:29 +02:00
parent e7b8ae6120
commit c8f37d0d98
65 changed files with 3309 additions and 3331 deletions

53
src/SomaSolver.ts Normal file
View File

@@ -0,0 +1,53 @@
import VoxelSpace from "./VoxelSpace";
import SomaSolution from "./SomaSolution";
export default class SomaSolver {
private solutionCube: VoxelSpace;
private dim: number;
private solutions: SomaSolution[] = [];
private iterations: number = 0;
constructor(dimension: number) {
if (dimension % 1 !== 0 || dimension < 0) {
throw new Error("The argument 'dimension' must be a positive whole number");
}
this.dim = dimension;
this.solutionCube = new VoxelSpace(0, [dimension, dimension, dimension], Array(dimension**3).fill(0));
}
async solve(polycubes: VoxelSpace[]) {
if (polycubes.length === 0) {
throw new Error("You must pass at least one polycube to solve the puzzle.");
}
let cumulativeSize = polycubes.reduce((prev, curr) => prev + curr.size(), 0);
if (cumulativeSize !== this.dim**3) {
throw new Error(`The polycubes passed do not add up to exactly enough units to form a cube of dimension ${this.dim}! Got: ${cumulativeSize}, need: ${this.dim**3}`);
}
this.solutions = [];
const combosWithRots = polycubes.slice(1).map(polycube => polycube.getUniqueRotations().map((rot: VoxelSpace) => rot.getAllPositionsInCube(this.dim)).flat());
const combos = [polycubes[0].getAllPositionsInCube(this.dim), ...combosWithRots];
this.backtrackSolve(this.solutionCube, combos, new SomaSolution(this.dim));
this.solutions = SomaSolution.filterUnique(this.solutions);
}
getSolutions() {
return this.solutions.slice();
}
private backtrackSolve(workingSolution: VoxelSpace, polycubes: VoxelSpace[][], currentSoln: SomaSolution, depth = 0) {
const nextCubeGroup = polycubes[0];
for (let i = 0; i < nextCubeGroup.length; i++) {
const fusionAttempt = workingSolution.plus(nextCubeGroup[i]);
if (fusionAttempt) {
const nextSoln = currentSoln.clone();
nextSoln.addSpace(nextCubeGroup[i]);
if (polycubes.length === 1) {
this.solutions.push(nextSoln);
currentSoln = new SomaSolution(this.dim);
return;
} else {
this.backtrackSolve(fusionAttempt, polycubes.slice(1), nextSoln, depth + 1);
}
}
}
}
}