|
|
@@ -0,0 +1,115 @@
|
|
|
+
|
|
|
+function read(cb) {
|
|
|
+ require("fs").readFile('./input', 'utf8', (err, data) => {
|
|
|
+ data.split("\n").forEach((l)=> {
|
|
|
+ var data = l.split(/\D+/);
|
|
|
+ if (data.length == 2)
|
|
|
+ cb(new Flag(parseInt(data[0]), parseInt(data[1])));
|
|
|
+ });
|
|
|
+ cb(null);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function Flag(px, py) {
|
|
|
+ this.px = px;
|
|
|
+ this.py = py;
|
|
|
+ this.cover = [];
|
|
|
+}
|
|
|
+
|
|
|
+Flag.prototype.translate = function(vx, vy) {
|
|
|
+ this.px += vx;
|
|
|
+ this.py += vy;
|
|
|
+}
|
|
|
+
|
|
|
+function Map() {
|
|
|
+ this.flags = [];
|
|
|
+ this.infinite = [];
|
|
|
+ this.safe = [];
|
|
|
+ this.min = undefined;
|
|
|
+ this.max = undefined;
|
|
|
+}
|
|
|
+
|
|
|
+Map.prototype.closestFlag = function(px, py) {
|
|
|
+ var closest = null,
|
|
|
+ sum =0;
|
|
|
+ this.flags.forEach(f => {
|
|
|
+ var dist = Math.abs(px -f.px) +Math.abs(py -f.py);
|
|
|
+ if (closest == null || dist < closest.dist)
|
|
|
+ closest = { dist: dist, flag: [ f ] };
|
|
|
+ else if (closest.dist == dist)
|
|
|
+ closest.flag.push(f);
|
|
|
+ sum += dist;
|
|
|
+ });
|
|
|
+ return {
|
|
|
+ flags: closest.flag,
|
|
|
+ sum: sum
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+Map.prototype.fillMap = function() {
|
|
|
+ var bound = this.max +this.min;
|
|
|
+
|
|
|
+ for (var i =0; i < bound; ++i)
|
|
|
+ for (var j =0; j < bound; ++j) {
|
|
|
+ var closestFlag = this.closestFlag(i, j);
|
|
|
+ closestFlag.flags.forEach(f => {
|
|
|
+ if ((i == 0 || j == 0 || i == bound -1 || j == bound -1) && this.infinite.indexOf(f) == -1)
|
|
|
+ this.infinite.push(f);
|
|
|
+ });
|
|
|
+ if (closestFlag.flags.length == 1)
|
|
|
+ closestFlag.flags[0].cover.push({ x: i, y: j });
|
|
|
+ if (closestFlag.sum < 10000)
|
|
|
+ this.safe.push({ x: i, y: j });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Map.prototype.addFlag = function(f) {
|
|
|
+ this.min = this.min === undefined ? f.px : Math.min(f.px, this.min);
|
|
|
+ this.min = this.min === undefined ? f.py : Math.min(f.py, this.min);
|
|
|
+ this.max = this.max === undefined ? f.px : Math.max(f.px, this.max);
|
|
|
+ this.max = this.max === undefined ? f.py : Math.max(f.py, this.max);
|
|
|
+ this.flags.push(f);
|
|
|
+}
|
|
|
+
|
|
|
+Map.prototype.resize = function() {
|
|
|
+ var vx = -this.min;
|
|
|
+ this.flags.forEach((f) => f.translate(vx, vx));
|
|
|
+ this.min += vx;
|
|
|
+ this.max += vx;
|
|
|
+}
|
|
|
+
|
|
|
+function ex1() {
|
|
|
+ var m = new Map();
|
|
|
+ read((flag) => {
|
|
|
+ if (flag) {
|
|
|
+ m.addFlag(flag);
|
|
|
+ } else {
|
|
|
+ m.resize();
|
|
|
+ m.fillMap();
|
|
|
+
|
|
|
+ var maxFlag = null;
|
|
|
+ m.flags.forEach((f) => {
|
|
|
+ if (m.infinite.indexOf(f) === -1) {
|
|
|
+ maxFlag = maxFlag && maxFlag.cover.length >= f.cover.length ? maxFlag : f;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ console.log("largest area that isn't infinite: " +maxFlag.cover.length);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function ex2() {
|
|
|
+ var m = new Map();
|
|
|
+ read((flag) => {
|
|
|
+ if (flag) {
|
|
|
+ m.addFlag(flag);
|
|
|
+ } else {
|
|
|
+ m.fillMap();
|
|
|
+ console.log("found " +m.safe.length +" safe zones");
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+ex1();
|
|
|
+ex2();
|
|
|
+
|