function read(done) { require("fs").readFile('./input', 'utf8', (err, data) => { var coords = []; data.split("\n").some((l) => { var r = / *(-?\d+), *(-?\d+).*< *(-?\d+), *(-?\d+)/.exec(l); if (r) coords.push(new PointAndVector(parseInt(r[1]), parseInt(r[2]), parseInt(r[3]), parseInt(r[4]))); }); done(new Map(coords)); }); } function PointAndVector(px, py, vx, vy) { this.px = px; this.py = py; this.vx = vx; this.vy = vy; } PointAndVector.prototype.next = function(val) { this.px += val*this.vx; this.py += val*this.vy; } function Map(points) { this.points = points; this.init(); this.time = 0; } Map.prototype.init = function() { this.minX = this.points[0].px; this.maxX = this.points[0].px; this.minY = this.points[0].py; this.maxY = this.points[0].py; for (var i =1, nbPts = this.points.length; i < nbPts; ++i) { this.minX = Math.min(this.minX, this.points[i].px); this.maxX = Math.max(this.maxX, this.points[i].px); this.minY = Math.min(this.minY, this.points[i].py); this.maxY = Math.max(this.maxY, this.points[i].py); } } Map.prototype.next = function(val) { this.points.forEach(i => i.next(val)); this.init(); this.time += val; return this; } Map.prototype.print = function() { for (var i=this.minY; i <= this.maxY; ++i) { for (var j =this.minX; j <= this.maxX; ++j) process.stdout.write(this.hasPoint(j, i) ? 'X' : '.'); process.stdout.write("\n"); } } Map.prototype.hasPoint = function(px, py) { if (px < this.minX || py < this.minY || px > this.maxX || py > this.maxY) return false; return this.points.some((pt) => pt.px == px && pt.py == py); } Map.prototype.isIsolated = function(px, py) { var hasPoint = false, count =0; this.points.some((pt) => { if (pt.px >= px -1 && pt.px <= px +1 && pt.py >= py -1 && pt.py <= py +1) { if (pt.px == px && pt.py == py) hasPoint = true; else count++; } return hasPoint && count > 0; }); return hasPoint && count == 0; } Map.prototype.countIsolated = function() { var isolated = 0; for (var i=this.minY; i <= this.maxY; ++i) for (var j =this.minX; j <= this.maxX; ++j) if (this.isIsolated(j, i)) isolated++; return isolated; } Map.prototype.mapSize = function() { return (this.maxX -this.minX) * (this.maxY -this.minY); } function ex1() { read(map => { var prevIsolated = 0, currentIsolated = map.mapSize(); do { map.next(1); prevIsolated = currentIsolated; currentIsolated = map.mapSize(); } while (prevIsolated -currentIsolated > 0); console.log("start counting isolated"); map.next(-3); currentIsolated = map.countIsolated(); do { map.next(1); prevIsolated = currentIsolated; currentIsolated = map.countIsolated(); } while (prevIsolated -currentIsolated > 0); map.next(-1).print(); console.log(map.time); }); } ex1(); //ex2();