function read(cb) { require("fs").readFile('./input', 'utf8', (err, data) => { var world = new World(); data.split("\n").forEach((l) => { if (l.startsWith("initial state: ")) { world.initializeState(l.substr(15)); } else { var r = /([.#]+) => ([.#])/.exec(l); if (r) world.rules[r[1]] = r[2]; } }); cb(world); }); } function World() { this.initialState = []; this.rules = []; this.state = []; this.loop = 0; this.offset = 0; } World.prototype.initializeState = function(li) { for (var i =0, len = li.length; i < len; ++i) this.initialState.push(li[i] == '#'); this.state = this.initialState; } World.prototype.arrToString = function(pos) { var result = ""; for (var i =-2; i <= 2; ++i) result += (this.initialState[pos +i] ? '#' : '.'); return result; } World.prototype.step = function() { this.state = []; var offset = []; for (var i =-2; i < 0; ++i) { var state = this.rules[this.arrToString(i)]; if (state == '#') offset[-i] = true; else if (state == '.') offset[-i] = false; } for (var i =0, len = this.initialState.length +2; i < len; ++i) { var state = this.rules[this.arrToString(i)]; if (state == '#') this.state[i] = true; else if (state == '.') this.state[i] = false; } if (offset[2]) { this.state.splice(0, 0, offset[2], offset[1]) this.offset += 2; } else if (offset[1]) { this.state.splice(0, 0, offset[1]) ++this.offset; } this.initialState = this.state; ++this.loop; } World.prototype.count = function() { var result = 0; for (var i =0, len = this.initialState.length; i < len; ++i) if (this.initialState[i]) result += i -this.offset; return result; } World.prototype.run = function(max) { for (var i =0; i < max; ++i) this.step(); } function ex1() { read(world => { world.run(20); console.log(world.count()); }); } function ex2() { read(world => { world.run(500); console.log(world.count() +(50000000000 -500) *36); }); } ex1(); ex2();