UNPKG

dlx

Version:

Knuth's Dancing Links algorithm for the exact cover problem

135 lines (117 loc) 2.54 kB
/* * To understand this pretty data structure, read Knuth's paper. * * TODO: Provide a short explanation here. */ var _ = require("underscore"); var convert = require("./convert.js"); function Node(x, y) { this.x = x; this.y = y; this.size = 0; this.l = this; this.r = this; this.u = this; this.d = this; }; Node.prototype.hide_lr = function() { this.l.r = this.r; this.r.l = this.l; }; Node.prototype.hide_ud = function() { this.u.d = this.d; this.d.u = this.u; }; Node.prototype.show_lr = function() { this.l.r = this; this.r.l = this; }; Node.prototype.show_ud = function() { this.u.d = this; this.d.u = this; }; Node.prototype.set_l = function(l) { l.l = this.l; l.r = this; this.l.r = l; this.l = l; }; Node.prototype.set_u = function(u) { u.u = this.u; u.d = this; this.u.d = u; this.u = u; }; function LinkedMatrix() { this.root = new Node(-1, -1); this.cols = []; }; LinkedMatrix.prototype.cover_column = function(col) { if (typeof col === 'number') { col = this.cols[col]; } col.hide_lr(); for (var row = col.d; row !== col; row = row.d) { for (var node = row.r; node !== row; node = node.r) { node.hide_ud(); --this.cols[node.x].size; } } }; LinkedMatrix.prototype.uncover_column = function(col) { if (typeof col === 'number') { col = this.cols[col]; } col.show_lr(); for (var row = col.u; row !== col; row = row.u) { for (var node = row.l; node !== row; node = node.l) { node.show_ud(); ++this.cols[node.x].size; } } }; LinkedMatrix.prototype.to_sparse = function() { var sparse = []; var put = function(x, y) { while (sparse.length <= y) { sparse.push([]); } sparse[y].push(x); }; for (var col = this.root.r; col !== this.root; col = col.r) { for (var row = col.d; row !== col; row = row.d) { put(col.x, row.y); } } _.invoke(sparse, 'sort'); return sparse; }; LinkedMatrix.from_sparse = function(sparse) { if (sparse == null) { return null; } var lm = new LinkedMatrix(); var col = function(x) { while (lm.cols.length <= x) { var node = new Node(lm.cols.length, -1); lm.root.set_l(node); lm.cols.push(node); } return lm.cols[x]; }; _.each(sparse, function (xs, y) { var row = new Node(-1, y); _.each(xs, function (x) { var node = new Node(x, y); col(x).set_u(node); ++col(x).size; row.set_l(node); }); row.hide_lr(); }); return lm; }; LinkedMatrix.from_dense = function(dense) { return LinkedMatrix.from_sparse(convert.dense_to_sparse(dense)); }; module.exports = LinkedMatrix;