function Claim(line) { line = line.split(/\D+/).filter(r => r.length > 0); this.id = parseInt(line[0]); this.px = parseInt(line[1]); this.py = parseInt(line[2]); this.width = parseInt(line[3]); this.height = parseInt(line[4]); } function read(cb) { require("fs").readFile('./input', 'utf8', (err, data) => { var lines = []; data.split("\n").forEach((line) => { if (line.length > 0) cb(new Claim(line)); }); cb(null); }); } function Fabric() { this.claimed = []; } Fabric.prototype.claim = function(id, x, y) { var alreadyClaimed = false; this.claimed[x] = this.claimed[x] || []; this.claimed[x][y] = 1 +(this.claimed[x][y] || 0); } Fabric.prototype.claimArea = function(claim) { for (var i = 0; i < claim.width; ++i) for (var j =0; j < claim.height; ++j) this.claim(claim.id, claim.px +i, claim.py +j); } Fabric.prototype.countMultipleClaimedAreas = function() { var areas = 0; this.claimed.forEach(function(c) { c.forEach(function(r) { if (r > 1) ++areas; }); }); return areas; } Fabric.prototype.isIntactInch = function(px, py) { return (this.claimed[px] || [])[py] === 1; } Fabric.prototype.isIntact = function(claim) { var intact = true; for (var i = 0; i < claim.width && intact; ++i) for (var j =0; j < claim.height && intact; ++j) intact &= this.isIntactInch(claim.px +i, claim.py +j); return intact; }; function run() { var f = new Fabric(), allClaims = []; read(function(claim) { if (claim) { f.claimArea(claim); allClaims.push(claim); } else { console.log("Overlap count: ", f.countMultipleClaimedAreas()); allClaims.some(function(c) { if (f.isIntact(c)) { console.log("Intact claim: ", c); return true; } return false; }); } }); } run();