Skip to content

Commit

Permalink
Repurpose builder.ts for Constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
MrHen committed Mar 31, 2016
1 parent f1123be commit 61a1f46
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 92 deletions.
169 changes: 82 additions & 87 deletions src/builder.ts
Original file line number Diff line number Diff line change
@@ -1,95 +1,90 @@
/// <reference path="./LatinHive.ts" />

interface LatinConstraint {
inner: string;
node: LatinHive.LatinNode;
outer: string;
skip: boolean;
value: boolean;
}

interface LatinConstraintMatrix {
[outer: string]: {
[inner: string]: LatinConstraint;
};
}

interface LatinSolution {
nodes: LatinHive.LatinNode[];
s?: number;
success: boolean;
valid?: boolean;
}

// Generate a suitable constraints matrix. Columns are the outer dimension
// (R1#1, R1#2, etc.) and rows are the inner dimension (R1C1#1, R1C1#2, etc.).
//
// Dancing links will convert these to a linked matrix but it is a little
// easier to grok what is happening if we split up the constraint generation
// and the linked matrix builder.
function buildConstraints(size: number, nodes: LatinHive.LatinNode[]) {
let sparse = false;
let matrix: LatinConstraintMatrix = {};

// Use the existing data cells instead of three loops so we can prune hints
nodes.forEach((node) => {
let i = node.cell.y + 1;
let j = node.cell.x + 1;
let k = node.guess;

let key = "R" + i + "C" + j;
let skip = node.cell.guess && node.cell.guess !== k;

if (sparse && skip) {
return;
}

let constraint: LatinConstraint;
for (let a = 1; a <= size; a++) {
for (let b = 1; b <= size; b++) {
matrix["R" + a + "#" + b] = matrix["R" + a + "#" + b] || {};
matrix["C" + a + "#" + b] = matrix["C" + a + "#" + b] || {};
matrix["R" + a + "C" + b] = matrix["R" + a + "C" + b] || {};

constraint = {
outer: "R" + a + "#" + b,
inner: key + "#" + k,
node: node,
skip: skip,
value: (a === i && b === k)
};

if (constraint.value || !sparse) {
matrix[constraint.outer][constraint.inner] = constraint;
}

constraint = {
outer: "C" + a + "#" + b,
inner: key + "#" + k,
node: node,
skip: skip,
value: (a === j && b === k)
};

if (constraint.value || !sparse) {
matrix[constraint.outer][constraint.inner] = constraint;
}

constraint = {
outer: "R" + a + "C" + b,
inner: key + "#" + k,
node: node,
skip: skip,
value: (a === i && b === j)
};
namespace LatinConstraint {
export interface LatinConstraint {
inner: string;
node: LatinHive.LatinNode;
outer: string;
skip: boolean;
value: boolean;
}

export interface LatinConstraintMatrix {
[outer: string]: {
[inner: string]: LatinConstraint;
};
}

// Generate a suitable constraints matrix. Columns are the outer dimension
// (R1#1, R1#2, etc.) and rows are the inner dimension (R1C1#1, R1C1#2, etc.).
//
// Dancing links will convert these to a linked matrix but it is a little
// easier to grok what is happening if we split up the constraint generation
// and the linked matrix builder.
export function buildConstraints(size: number, nodes: LatinHive.LatinNode[]) {
let sparse = false;
let matrix: LatinConstraintMatrix = {};

// Use the existing data cells instead of three loops so we can prune hints
nodes.forEach((node) => {
let i = node.cell.y + 1;
let j = node.cell.x + 1;
let k = node.guess;

let key = "R" + i + "C" + j;
let skip = node.cell.guess && node.cell.guess !== k;

if (sparse && skip) {
return;
}

if (constraint.value || !sparse) {
matrix[constraint.outer][constraint.inner] = constraint;
let constraint: LatinConstraint;
for (let a = 1; a <= size; a++) {
for (let b = 1; b <= size; b++) {
matrix["R" + a + "#" + b] = matrix["R" + a + "#" + b] || {};
matrix["C" + a + "#" + b] = matrix["C" + a + "#" + b] || {};
matrix["R" + a + "C" + b] = matrix["R" + a + "C" + b] || {};

constraint = {
outer: "R" + a + "#" + b,
inner: key + "#" + k,
node: node,
skip: skip,
value: (a === i && b === k)
};

if (constraint.value || !sparse) {
matrix[constraint.outer][constraint.inner] = constraint;
}

constraint = {
outer: "C" + a + "#" + b,
inner: key + "#" + k,
node: node,
skip: skip,
value: (a === j && b === k)
};

if (constraint.value || !sparse) {
matrix[constraint.outer][constraint.inner] = constraint;
}

constraint = {
outer: "R" + a + "C" + b,
inner: key + "#" + k,
node: node,
skip: skip,
value: (a === i && b === j)
};

if (constraint.value || !sparse) {
matrix[constraint.outer][constraint.inner] = constraint;
}
}
}
}

});
});

return matrix;
return matrix;
}
}
8 changes: 4 additions & 4 deletions src/draw.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// <reference path="./builder.ts" />

function drawConstraints(constraints: LatinConstraintMatrix) {
function drawConstraints(constraints: LatinConstraint.LatinConstraintMatrix) {
let height = constraintsSvg.attr("height");
let width = constraintsSvg.attr("width");

Expand All @@ -11,9 +11,9 @@ function drawConstraints(constraints: LatinConstraintMatrix) {
.domain([0, 1])
.range([latinColors.colors["invalid"], latinColors.colors["valid"]]);

let flat: LatinConstraint[] = _.flatten<any>(_.map(_.values(constraints), _.values));
let columnLabels: string[] = _.uniq(_.map<LatinConstraint, string>(flat, columnIndex)).sort();
let rowLabels: string[] = _.uniq(_.map<LatinConstraint, string>(flat, rowIndex)).sort();
let flat: LatinConstraint.LatinConstraint[] = _.flatten<any>(_.map(_.values(constraints), _.values));
let columnLabels: string[] = _.uniq(_.map<LatinConstraint.LatinConstraint, string>(flat, columnIndex)).sort();
let rowLabels: string[] = _.uniq(_.map<LatinConstraint.LatinConstraint, string>(flat, rowIndex)).sort();

let labelOffset = 4;
let maxWidth = +width / (columnLabels.length + 2 + labelOffset);
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ let cells: square.LatinCell[] = latinSquare.build();
// One for each cell + guess combination (n^3 = 64 at size 4)
let nodes: LatinHive.LatinNode[] = latinHive.buildNodes(cells);

let constraints: LatinConstraintMatrix = buildConstraints(size, nodes);
let constraints: LatinConstraint.LatinConstraintMatrix = LatinConstraint.buildConstraints(size, nodes);
let result = dlx.solveWithDancingLinks(constraints, true);
let solutions: LatinHive.LatinSolution[] = result.solutions;

Expand Down

0 comments on commit 61a1f46

Please sign in to comment.