| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- function readAll(cb) {
- require("fs").readFile('./input', 'utf8', (err, data) => {
- var world = new World();
- data.split("\n").forEach(line => {
- if (!line)
- return;
- var numbers = line.match(/(\d+)/g).map(i => parseInt(i));
- if (line.charAt(0) == 'x')
- world.addData(numbers[0], numbers[0], numbers[1], numbers[2], 'x');
- else
- world.addData(numbers[1], numbers[2], numbers[0], numbers[0], 'x');
- });
- cb(world);
- });
- }
- function World() {
- this.data = {};
- this.sources = [[ 500, 0 ]];
- this.minX = 500;
- this.maxX = 500;
- this.minY = 0;
- this.maxY = 0;
- }
- World.prototype.addData = function(x1, x2, y1, y2, type) {
- while (y1 <= y2) {
- for (var j = x1; j <= x2; ++j) {
- this.data[y1] = this.data[y1] || {};
- this.data[y1][j] = type;
- }
- ++y1;
- }
- this.minX = Math.min(x1, this.minX);
- this.maxX = Math.max(x2, this.maxX);
- if (type == 'x') {
- this.minY = Math.min(y1, this.minY);
- this.maxY = Math.max(y2, this.maxY);
- }
- }
- World.prototype.getChar = function(x, y, defaultValue) {
- return this.data[y] ? this.data[y][x] || defaultValue : defaultValue;
- }
- World.prototype.isEmpty = function(x, y) {
- var c = this.getChar(x, y, false);
- return !c || c == '|';
- }
- World.prototype.nextClay = function(x, y, direction) {
- for (; x >= this.minX && x <= this.maxX; x += direction) {
- if (this.isEmpty(x, y +1))
- return false;
- if (!this.isEmpty(x, y))
- return x;
- }
- return false;
- }
- World.prototype.trySettle = function(minX, maxX, y) {
- if (minX === false || maxX === false || minX === maxX)
- return false;
- this.addData(minX +1, maxX -1, y, y, '~');
- return true;
- }
- World.prototype.water = function() {
- var x = this.sources[0][0],
- y = this.sources[0][1];
- while (this.isEmpty(x, y +1) && y <= this.maxY)
- ++y;
- if (y <= this.maxY) {
- var minX = this.nextClay(x, y, -1),
- maxX = this.nextClay(x, y, +1);
- if (this.trySettle(minX, maxX, y))
- return;
- var found = false;
- for (var tmp = x; this.isEmpty(tmp, y); ++tmp) {
- this.addData(tmp, tmp, y, y, '|');
- if (this.isEmpty(tmp, y +1)) {
- this.sources.push([ tmp, y ]);
- break;
- }
- }
- for (var tmp = x; this.isEmpty(tmp, y); --tmp) {
- this.addData(tmp, x, y, y, '|');
- if (this.isEmpty(tmp, y +1)) {
- this.addData(tmp, x, y, y, '|');
- this.sources.push([ tmp, y ]);
- break;
- }
- }
- }
- this.addData(x, x, this.sources[0][1], y, '|');
- this.sources.splice(0, 1);
- }
- World.prototype.countWater = function() {
- var count = { settled: 0, unsettled: 0 };
- for (var i in this.data)
- if (i != 0)
- for (var j in this.data[i])
- switch (this.data[i][j]) {
- case '~':
- ++count.settled;
- break;
- case '|':
- ++count.unsettled;
- break;
- }
- count.total = count.settled +count.unsettled;
- return count;
- }
- World.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.getChar(j, i, ' '));
- process.stdout.write("\n");
- }
- }
- function run() {
- readAll(world => {
- while (world.sources.length)
- world.water();
- //world.print();
- console.log("Water cell: ", world.countWater());
- });
- }
- run();
|