diff --git a/2020/day-11/index.js b/2020/day-11/index.js new file mode 100644 index 0000000..af7e035 --- /dev/null +++ b/2020/day-11/index.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-unused-vars +const console = require('../helpers') +require('./solution') diff --git a/2020/day-11/input.txt b/2020/day-11/input.txt new file mode 100644 index 0000000..6577da1 --- /dev/null +++ b/2020/day-11/input.txt @@ -0,0 +1,91 @@ +LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLL.LLLLLLLL..LLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLL.LLLLLLLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLL.LLLL.LL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +...L.L......L...L..L...L..LL.....L.....L..LLLL..L.LL......LL....L..L.L..L....L.LL....LL..L..L +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLL.LLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLL..LLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLL.LLLLLLLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL..LLLLLLLLLLLLLLLLL.LLLLLLLL.LLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLL +LLLL.LLLLL.LLLL.LLL.LLLLLLLLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +.....L.LLLL....LL..L...LLL.L.LL..LL.L........L....LL...L...L...L.LL....LL...L..L.....LL.L.... +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LL.LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LL.LLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL..LLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLL.LLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLL..LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLL.LLLLLLLLLL.LLLLL.LL.LLLLLLLLLL +...L......L....L....L......L.L.....L..L.L.L..L.L...LLL.....LLLL.L.......LL.LLL.L.LL....L..... +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LL.LLLLLLLLLLLLLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLL.L.LLLL.LLL +LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LL.L.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLL +...LL..........L..LLLLL...L.L..........L........L.LL..L..L.LLL.L..L.L.....LL...LL....L..L.L.. +LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLL.LLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL..LLLLLL.LLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLL.LLLLL.LLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLL.LLL.LLLL.LLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLL.LLLL.LLLLL..LLLLLLL.LLLLLLLLLL +LLLLLLLLL..L.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLL +..LLLL.LL....LLL..L...L..L..L.......L..L...L.L...L..LL.L.L.L.L...L...L.L.L.L.L......LL...L..L +LLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLLLLLL.LLLL.LLLLL.LLLLL.LLLLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLL.LLL.LLLLLLLL.L.LLLLLL.LLLL.LLLL.LLLLLLLL.LLLL.LLLLLL.LLLLLL..LLLLLL.LLL +..L...L...L...L..L....L...LL.L.L.L..LL...........LLL.L......L..L.....LL..L..LLL........L....L +LLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLL +LLLLLLL.LL.LLLL.LLLLLLL.L.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLL.L.LLLL.LLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLL.LL.L.LLLLL +..L.L.LL....L....L..L....L.L...L..L..L.L.....L..L...L.LL.....L...............L..............L +LLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LL.L.LLLL.LLL.LLLL.LLLLL.LL.LLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LL.L.LLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLL.LL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +L.L.....L.L.L.LL.L......LLL.....L.L.L........L....LL.......L....L.....L....LL..L...LLL......L +LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLL.L.LLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLL..LLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLL.LLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +...L...L.....L....L.L..........L..L.L..L..L..LL.L..L.......L.......L....L....L...LLL..L..L..L +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLL +..LLL....L.LL....L..............LLL......LL.LLL.....LL..L.L..L........L......L...L.LL..LL..L. +LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLL.LLL..LLLLLLLLLLLLLL.LLLLLLLLLL +L.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLL.LLL...LLLLLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLL..LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLL.LLL.LLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL +L...L.LL......L...LLLLLL.L.L.L...L.L..L..L.LL....L......LL..L...LLL....L...LL......L......... +LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLL +LLLLLLLLLL.LLL..LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLL.LLLL +LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLL diff --git a/2020/day-11/seating.js b/2020/day-11/seating.js new file mode 100644 index 0000000..56e750a --- /dev/null +++ b/2020/day-11/seating.js @@ -0,0 +1,112 @@ + +const parse = (data) => { + return data.split('\n').map((row) => { + return row.split('') + }) +} + +const format = (seatMap) => { + return seatMap.map((row) => row.join('')).join('\n') +} + +const occupiedLineOfSite = ({ x, y, seatMap }) => { + let occupied = 0 + const look = ({ lookX, lookY, dirX, dirY }) => { + if (lookY < 0 || lookY >= seatMap.length) { + // exceeded rows space + return 'x' + } + if (lookX < 0 || lookX >= seatMap[0].length) { + // exceeded column space + return 'x' + } + // Find the first seat in the direction, recursively + if (seatMap[lookY][lookX] !== '.') { + return seatMap[lookY][lookX] + } + + // Recursively look in the next seat in this direction + return look({ lookX: lookX + dirX, lookY: lookY + dirY, dirX, dirY }) + } + + // 8 compass point directions + for (let dirX = -1; dirX <= 1; dirX++) { + for (let dirY = -1; dirY <= 1; dirY++) { + if (look({ lookX: x + dirX, lookY: y + dirY, dirX, dirY }) === '#') { + occupied++ + } + } + } + + return occupied +} + +const occupiedNearby = ({ x, y, seatMap }) => { + let temp = '' + + for (let row = y - 1; row <= y + 1; row++) { + for (let col = x - 1; col <= x + 1; col++) { + try { + temp += seatMap[row][col] || '-' + } catch { + temp += '-' + } + } + temp += '\n' + } + const occupied = (temp.match(/#/g) || []).length + + // console.debug(temp) + // console.debug(`------${occupied}------------`) + return occupied +} + +const advance = (seatMap, rules) => { + return seatMap.map((row, y) => { + return row.map((col, x) => { + return update({ x, y, seatMap, rules }) + }) + }) +} + +const update = ({ x, y, seatMap, rules = 'proximity' }) => { + let leaveThreshold = 4 + let processor = occupiedNearby + if (rules === 'visibility') { + leaveThreshold = 5 + processor = occupiedLineOfSite + } + + let next = seatMap[y][x] + switch (seatMap[y][x]) { + case '.': + // Floor (.) never changes; seats don't move, and nobody sits on the floor. + next = seatMap[y][x] + break + case 'L': + // If a seat is empty (L) and there are no occupied seats adjacent to it, the seat becomes occupied. + if (processor({ x, y, seatMap }) === 0) { + next = '#' + } + break + case '#': + // If a seat is occupied (#) and four or more seats adjacent to it are also occupied, the seat becomes empty. + // We subtract 1 so we don't count the target seat + if (processor({ x, y, seatMap }) - 1 >= leaveThreshold) { + next = 'L' + } + break + default: + // Otherwise, the seat's state does not change. + next = seatMap[y][x] + } + + return next +} + +module.exports = { + format, + parse, + advance, + occupiedLineOfSite +} diff --git a/2020/day-11/seating.test.js b/2020/day-11/seating.test.js new file mode 100644 index 0000000..8ecd693 --- /dev/null +++ b/2020/day-11/seating.test.js @@ -0,0 +1,227 @@ +/* eslint-env mocha */ +const { expect } = require('chai') +const { format, parse, advance, occupiedLineOfSite } = require('./seating') + +const testData = [ +`L.LL.LL.LL +LLLLLLL.LL +L.L.L..L.. +LLLL.LL.LL +L.LL.LL.LL +L.LLLLL.LL +..L.L..... +LLLLLLLLLL +L.LLLLLL.L +L.LLLLL.LL` +] +testData.push( +`#.##.##.## +#######.## +#.#.#..#.. +####.##.## +#.##.##.## +#.#####.## +..#.#..... +########## +#.######.# +#.#####.##` +) +testData.push( +`#.LL.L#.## +#LLLLLL.L# +L.L.L..L.. +#LLL.LL.L# +#.LL.LL.LL +#.LLLL#.## +..L.L..... +#LLLLLLLL# +#.LLLLLL.L +#.#LLLL.##` +) +testData.push( +`#.##.L#.## +#L###LL.L# +L.#.#..#.. +#L##.##.L# +#.##.LL.LL +#.###L#.## +..#.#..... +#L######L# +#.LL###L.L +#.#L###.##` +) +testData.push( +`#.#L.L#.## +#LLL#LL.L# +L.L.L..#.. +#LLL.##.L# +#.LL.LL.LL +#.LL#L#.## +..L.L..... +#L#LLLL#L# +#.LLLLLL.L +#.#L#L#.##` +) +testData.push( +`#.#L.L#.## +#LLL#LL.L# +L.#.L..#.. +#L##.##.L# +#.#L.LL.LL +#.#L#L#.## +..L.L..... +#L#L##L#L# +#.LLLLLL.L +#.#L#L#.##` +) + +const testDataPart2 = [testData[0]] +testDataPart2.push( +`#.##.##.## +#######.## +#.#.#..#.. +####.##.## +#.##.##.## +#.#####.## +..#.#..... +########## +#.######.# +#.#####.##` +) +testDataPart2.push( +`#.LL.LL.L# +#LLLLLL.LL +L.L.L..L.. +LLLL.LL.LL +L.LL.LL.LL +L.LLLLL.LL +..L.L..... +LLLLLLLLL# +#.LLLLLL.L +#.LLLLL.L#` +) +testDataPart2.push( +`#.L#.##.L# +#L#####.LL +L.#.#..#.. +##L#.##.## +#.##.#L.## +#.#####.#L +..#.#..... +LLL####LL# +#.L#####.L +#.L####.L#` +) +testDataPart2.push( +`#.L#.L#.L# +#LLLLLL.LL +L.L.L..#.. +##LL.LL.L# +L.LL.LL.L# +#.LLLLL.LL +..L.L..... +LLLLLLLLL# +#.LLLLL#.L +#.L#LL#.L#` +) +testDataPart2.push( +`#.L#.L#.L# +#LLLLLL.LL +L.L.L..#.. +##L#.#L.L# +L.L#.#L.L# +#.L####.LL +..#.#..... +LLL###LLL# +#.LLLLL#.L +#.L#LL#.L#` +) +testDataPart2.push( +`#.L#.L#.L# +#LLLLLL.LL +L.L.L..#.. +##L#.#L.L# +L.L#.LL.L# +#.LLLL#.LL +..#.L..... +LLL###LLL# +#.LLLLL#.L +#.L#LL#.L#` +) + +describe('--- Day 11: Seating System ---', () => { + describe('Part 1', () => { + describe('advance()', () => { + it('advances the seating state', () => { + const results = testData.map((data) => { + return format( + advance( + parse(data) + ) + ) + }) + + for (let x = 1; x < testData.length; x++) { + console.debug('Step', x) + expect(results[x - 1]).to.equal(testData[x]) + } + const finalOccupancy = (results[results.length - 1].match(/#/g) || []).length + expect(finalOccupancy).to.equal(37) + }) + }) + }) + describe('Part 2', () => { + describe('occupiedLineOfSite()', () => { + it('counts the occupied seats visible in each direction', () => { + const data = +`.......#. +...#..... +.#....... +......... +..#L....# +....#.... +......... +#........ +...#.....` + expect(occupiedLineOfSite({ x: 3, y: 4, seatMap: parse(data) })).to.equal(8) + }) + it('cannot see occupied seats past an available seat', () => { + const data = +`............. +.L.L.#.#.#.#. +.............` + expect(occupiedLineOfSite({ x: 1, y: 1, seatMap: parse(data) })).to.equal(0) + }) + it('can look in all compass directions', () => { + const data = +`.##.##. +#.#.#.# +##...## +...L... +##...## +#.#.#.# +.##.##.` + expect(occupiedLineOfSite({ x: 3, y: 3, seatMap: parse(data) })).to.equal(0) + }) + }) + describe('advance()', () => { + it('accepts visibility rules instead of proximity', () => { + const results = testDataPart2.map((data) => { + return format( + advance( + parse(data), 'visibility' + ) + ) + }) + + for (let x = 1; x < testDataPart2.length; x++) { + console.debug('Step', x) + console.debug(results[x - 1]) + expect(results[x - 1]).to.equal(testDataPart2[x]) + } + const finalOccupancy = (results[results.length - 1].match(/#/g) || []).length + expect(finalOccupancy).to.equal(26) + }) + }) + }) +}) diff --git a/2020/day-11/solution.js b/2020/day-11/solution.js new file mode 100644 index 0000000..4537a8f --- /dev/null +++ b/2020/day-11/solution.js @@ -0,0 +1,49 @@ +const fs = require('fs') +const path = require('path') +const filePath = path.join(__dirname, 'input.txt') +const { parse, advance, format } = require('./seating') + +fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { + if (err) throw err + + initData = initData.trim() + + const resetInput = () => { + // Deep copy to ensure we aren't mutating the original data + return JSON.parse(JSON.stringify(initData)) + } + + const part1 = () => { + let data = resetInput() + let last = 0 + let curr = 1 + while (curr !== last) { + last = curr + data = format(advance(parse(data))) + // count the current occupied seats + curr = (data.match(/#/g) || []).length + } + return curr + } + + const part2 = () => { + let data = resetInput() + let last = 0 + let curr = 1 + while (curr !== last) { + last = curr + data = format(advance(parse(data), 'visibility')) + // count the current occupied seats + curr = (data.match(/#/g) || []).length + } + return curr + } + const answers = [] + answers.push(part1()) + answers.push(part2()) + + answers.forEach((ans, idx) => { + console.info(`-- Part ${idx + 1} --`) + console.info(`Answer: ${ans}`) + }) +})