diff --git a/2021/day-04/bingo.js b/2021/day-04/bingo.js new file mode 100644 index 0000000..b6a26c0 --- /dev/null +++ b/2021/day-04/bingo.js @@ -0,0 +1,63 @@ +const markBoard = (board, called) => { + for (let x = 0; x < 5; x++) { + for (let y = 0; y < 5; y++) { + if (board[x][y] === called) { + board[x][y] = 'x' + // TODO: speed up break the loop, since only one of a number on each board + // x = 6 + // y = 6 + } + } + } + return board +} + +const checkWinner = (board) => { + // TODO: This can be sped up by doing a check for at least 5 "x" before + // validating horizontal/vertical explicitly. Another speedup would be to + // zig-zag check parse through the array and break/resolve when there + // isn't a match instead of checking all columns then checking all rows + + // Look for a horizontal bingo + for (let y = 0; y < 5; y++) { + if (board[y].filter((val) => val === 'x').length === 5) { + return 'winner' + } + } + + // Look for a vertical bingo + let match = 0 + for (let x = 0; x < 5; x++) { + for (let y = 0; y < 5; y++) { + if (board[y][x] === 'x') { + match++ + + if (match === 5) { + return 'winner' + } + } + } + match = 0 // reset so next row has a clean count + } + + // No bingo + return 'no win' +} + +const scoreBoard = (board) => { + return board.reduce((tally, row) => { + tally += row.reduce((colTally, cell) => { + if (cell !== 'x') { + colTally += cell + } + return colTally + }, 0) + return tally + }, 0) +} + +module.exports = { + scoreBoard, + checkWinner, + markBoard +} diff --git a/2021/day-04/bingo.test.js b/2021/day-04/bingo.test.js new file mode 100644 index 0000000..cc77f84 --- /dev/null +++ b/2021/day-04/bingo.test.js @@ -0,0 +1,106 @@ +/* eslint-env mocha */ +const { expect } = require('chai') +const { scoreBoard, checkWinner, markBoard } = require('./bingo') +const { parseData, linesToArray } = require('../../2018/inputParser') + +const testData = ` +7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 + +22 13 17 11 0 + 8 2 23 4 24 +21 9 14 16 7 + 6 10 3 18 5 + 1 12 20 15 19 + + 3 15 0 2 22 + 9 18 13 17 5 +19 8 7 25 23 +20 11 10 24 4 +14 21 16 12 6 + +14 21 17 24 4 +10 16 15 9 19 +18 8 23 26 20 +22 11 13 6 5 + 2 0 12 3 7 +` +// Deep copy to ensure we aren't mutating the original data +const data = JSON.parse(JSON.stringify(linesToArray(testData))) + +// split up data +const testDraws = parseData(data.shift()) +console.debug(testDraws) +const testBoards = [] +for (let x = 0; x < data.length; x = x + 5) { + testBoards.push( + data.slice(x, x + 5).map(parseData) + ) +} + +describe('--- Day 4: Giant Squid ---', () => { + describe('Part 1', () => { + describe('markBoard()', () => { + it('checks a board for a match and marks it', () => { + const board = [ + [1, 2, 3, 4, 5], + [9, 8, 7, 6, 5], + ['x', 'x', 'x', 'x', 'x'], + [3, 6, 9, 1, 0], + [1, 3, 5, 7, 9] + ] + const expected = [ + [1, 2, 3, 4, 'x'], + [9, 8, 7, 6, 'x'], + ['x', 'x', 'x', 'x', 'x'], + [3, 6, 9, 1, 0], + [1, 3, 'x', 7, 9] + ] + expect(markBoard(board, 5)).to.deep.equal(expected) + }) + }) + describe('checkWinner()', () => { + it('checks to see if a board has a horizontal bingo', () => { + const board = [ + [1, 2, 3, 4, 5], + [9, 8, 7, 6, 5], + ['x', 'x', 'x', 'x', 'x'], + [3, 6, 9, 1, 0], + [1, 3, 5, 7, 9] + ] + expect(checkWinner(board)).to.equal('winner') + }) + it('checks to see if a board has a vertical bingo', () => { + const board = [ + [1, 2, 3, 'x', 5], + [9, 8, 7, 'x', 5], + [2, 4, 6, 'x', 8], + [3, 6, 9, 'x', 0], + [1, 3, 5, 'x', 7] + ] + expect(checkWinner(board)).to.equal('winner') + }) + it('identifies a board is not yet a winner', () => { + const board = [ + [1, 'x', 3, 4, 5], + [9, 8, 7, 'x', 5], + ['x', 'x', 3, 7, 11], + [3, 6, 9, 'x', 'x'], + [1, 3, 5, 7, 'x'] + ] + expect(checkWinner(board)).to.equal('no win') + }) + }) + describe('scoreBoard()', () => { + it('gets the sum of the unmarked squares on the board', () => { + const board = [ + ['x', 'x', 'x', 'x', 'x'], + [10, 16, 15, 'x', 19], + [18, 8, 'x', 26, 20], + [22, 'x', 13, 6, 'x'], + ['x', 'x', 12, 3, 'x'] + ] + expect(scoreBoard(board)).to.equal(188) + }) + }) + }) +}) diff --git a/2021/day-04/index.js b/2021/day-04/index.js new file mode 100644 index 0000000..af7e035 --- /dev/null +++ b/2021/day-04/index.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-unused-vars +const console = require('../helpers') +require('./solution') diff --git a/2021/day-04/input.txt b/2021/day-04/input.txt new file mode 100644 index 0000000..5bab2b0 --- /dev/null +++ b/2021/day-04/input.txt @@ -0,0 +1,601 @@ +1,76,38,96,62,41,27,33,4,2,94,15,89,25,66,14,30,0,71,21,48,44,87,73,60,50,77,45,29,18,5,99,65,16,93,95,37,3,52,32,46,80,98,63,92,24,35,55,12,81,51,17,70,78,61,91,54,8,72,40,74,68,75,67,39,64,10,53,9,31,6,7,47,42,90,20,19,36,22,43,58,28,79,86,57,49,83,84,97,11,85,26,69,23,59,82,88,34,56,13 + +85 23 65 78 93 +27 53 10 12 26 + 5 34 83 25 6 +56 40 73 29 54 +33 68 41 32 82 + + 8 31 14 70 91 +53 49 86 13 21 +66 28 76 78 93 +39 63 80 43 23 +56 25 60 67 72 + +67 78 36 64 14 +46 16 80 23 94 +22 47 51 65 57 +33 76 21 92 97 +31 95 54 27 20 + + 1 77 86 43 30 +28 88 7 5 60 +66 24 3 57 33 +38 23 59 84 44 +74 47 17 29 85 + +21 50 86 2 70 +85 19 22 93 25 +99 38 74 30 65 +81 0 47 78 63 +34 11 51 88 64 + +45 15 29 81 30 +75 21 88 91 49 +39 20 4 17 78 +10 12 38 11 7 +98 6 65 69 86 + +36 20 31 44 69 +30 65 55 88 64 +74 85 82 61 5 +57 17 90 43 54 +58 83 52 23 7 + +42 16 82 86 76 +60 26 27 59 55 + 7 53 22 78 5 +18 61 10 15 17 +28 46 14 87 77 + +21 43 15 47 61 +24 76 28 3 27 +19 62 69 82 93 +49 29 97 74 41 +92 36 37 99 40 + +31 4 3 62 51 +24 57 78 67 53 +13 5 76 38 55 +79 9 75 98 71 +65 1 39 18 47 + +59 4 38 95 99 +85 68 69 93 43 +83 57 48 42 15 +47 50 80 79 90 +56 87 78 64 25 + +21 37 14 67 95 +88 39 26 38 49 +89 83 54 77 96 +48 86 94 19 20 +43 41 8 74 58 + + 1 36 12 90 91 +63 21 98 82 66 +39 86 7 52 77 +80 81 44 33 58 +78 30 11 51 28 + +81 74 7 33 96 +75 60 87 47 91 +39 73 30 50 13 + 4 41 9 43 77 +34 82 72 48 12 + +93 63 74 25 57 +29 76 9 45 70 +98 77 71 16 41 +47 54 18 14 55 +31 89 67 87 83 + + 8 72 45 93 68 +74 26 69 94 65 +28 9 20 47 41 +46 54 21 56 22 +84 62 18 15 48 + +20 51 81 40 69 +71 10 13 93 75 +44 86 0 95 37 +99 39 76 80 66 +14 64 49 62 27 + +75 7 51 86 79 +43 30 61 39 16 +85 63 90 28 96 +88 78 72 31 73 +98 87 23 19 58 + +20 95 47 97 12 +92 25 68 87 91 +37 10 78 23 63 +74 93 58 39 5 +76 51 48 72 16 + +37 18 32 34 85 +22 31 98 42 19 +29 72 48 76 25 +47 1 21 7 53 +79 82 86 52 78 + +20 16 47 78 92 +88 15 71 67 2 + 5 52 90 70 9 +22 49 28 82 27 + 6 19 61 73 48 + +71 26 7 11 79 +52 30 47 1 31 +17 75 94 91 28 +81 98 23 55 21 +77 15 39 24 16 + + 5 75 44 88 65 +89 45 23 69 19 +41 61 67 52 54 +47 38 57 12 98 +62 70 26 87 53 + +50 4 65 77 25 + 6 21 5 27 92 +39 63 97 75 79 +60 34 87 26 74 +99 24 44 85 2 + +13 64 38 78 21 +74 17 83 57 94 +25 39 69 53 4 +54 33 81 50 76 +42 75 19 77 26 + +63 31 70 19 39 +38 87 15 90 75 +61 98 6 29 86 +78 62 32 11 60 +55 97 13 73 82 + +51 63 68 84 36 +12 33 37 31 8 +18 41 34 74 23 +72 39 85 48 60 +24 19 29 88 0 + +46 51 17 23 13 +20 93 97 99 81 +57 47 33 84 44 +28 96 2 43 56 +68 36 62 15 5 + +81 99 5 30 10 +38 62 57 8 37 + 7 86 98 3 54 +46 82 96 15 72 +83 1 75 25 50 + +47 57 11 61 27 +53 10 31 91 98 +76 85 55 38 23 + 6 81 67 71 70 +35 29 17 50 56 + +24 65 15 1 89 +45 60 97 23 14 +84 56 58 5 54 + 3 72 51 46 79 +67 70 78 34 77 + +38 11 54 23 2 +33 14 10 96 63 +43 5 36 20 30 +70 53 66 71 9 +91 90 21 7 88 + +94 44 4 86 26 +39 70 54 50 30 +55 40 12 72 71 +68 7 66 47 91 +31 24 13 1 96 + +79 14 40 87 68 +16 32 53 46 98 +38 95 21 89 69 +62 60 19 81 33 +70 52 28 83 0 + +62 42 38 48 64 +61 79 78 97 98 +89 7 3 29 68 +92 76 14 67 1 +41 99 72 47 60 + + 5 75 18 42 33 +72 61 36 31 29 +19 58 1 34 94 +54 84 92 99 38 +76 68 79 53 37 + +14 91 37 5 98 +68 29 34 76 43 +75 0 67 33 69 +81 47 58 30 93 +88 92 42 77 54 + +64 24 28 54 53 +72 68 3 73 4 +83 6 59 66 94 +87 80 55 20 16 +13 82 74 31 70 + +63 92 71 0 83 +98 40 50 55 2 +88 5 85 30 23 +10 75 81 58 68 +51 31 14 89 1 + +67 93 94 54 53 +38 71 34 40 24 +31 63 30 99 75 + 4 57 86 19 70 +60 49 87 68 74 + +56 94 79 53 7 +24 12 19 6 99 +82 51 41 46 43 +17 49 52 78 55 +75 48 61 70 87 + +14 55 32 21 31 +88 83 23 44 4 + 1 77 45 90 85 +46 81 51 27 62 +60 24 29 18 0 + +95 92 91 27 26 +22 43 45 64 62 +83 23 25 85 94 +84 53 72 28 20 +75 60 52 18 73 + +95 41 7 21 32 +58 65 16 56 97 +68 25 91 83 24 +66 89 15 55 6 + 2 30 84 10 90 + +58 86 44 19 74 +57 89 17 6 83 +77 35 60 32 13 +97 63 62 28 76 +55 31 11 0 52 + +33 39 59 42 45 +61 50 92 9 79 +15 0 28 5 72 +91 24 21 29 87 +86 76 43 31 93 + +63 11 86 45 85 +96 74 66 93 32 +95 30 99 23 18 +69 97 48 15 1 +42 87 47 83 80 + +93 5 40 64 2 +44 51 15 54 83 +69 77 90 58 11 + 0 48 43 30 55 +25 72 38 73 52 + +89 58 71 68 15 +23 65 9 36 74 +21 29 42 79 98 +55 47 33 39 28 +16 75 91 69 57 + +13 79 12 71 2 +60 94 99 43 82 +84 89 29 91 87 +74 80 25 32 21 +70 14 68 92 11 + +78 1 16 51 87 +58 94 59 15 43 +79 41 50 47 39 +53 37 9 28 72 +34 63 89 35 18 + +31 67 70 42 43 +60 2 89 49 22 +56 17 81 24 74 +20 65 1 96 51 +68 7 0 38 25 + +59 14 29 53 19 + 9 2 11 33 44 +81 6 10 47 58 +20 34 62 55 40 +71 38 69 45 78 + +59 36 70 42 21 + 3 16 49 79 98 +74 25 8 84 19 +61 80 47 65 64 +91 62 52 9 40 + + 1 85 63 7 2 + 0 20 61 26 77 +99 37 74 42 76 +25 94 19 78 60 +79 72 95 22 11 + +51 21 79 76 32 +55 23 69 19 61 +71 54 94 47 92 + 5 64 6 68 16 +91 81 9 99 30 + +61 69 82 86 68 +66 81 28 38 36 +26 29 31 11 8 +72 51 12 95 63 +18 30 88 17 32 + +34 8 14 42 67 +66 79 65 20 52 +37 87 74 24 3 +59 54 21 32 89 +31 4 62 76 30 + +11 93 8 92 55 +38 72 99 3 83 +12 75 0 41 46 +17 25 5 39 48 +14 18 86 29 84 + + 6 20 41 51 48 + 5 67 30 24 47 + 3 8 92 22 39 + 4 56 36 31 75 + 2 45 85 81 96 + +47 43 72 22 3 +19 87 53 12 60 +29 40 56 68 18 +66 97 70 33 39 +85 37 0 90 98 + +61 35 81 84 94 +11 1 58 45 77 + 6 99 67 36 43 + 5 7 0 87 80 +44 78 39 70 20 + +58 34 49 29 75 +17 15 28 23 84 +59 25 92 48 0 +20 81 47 3 71 +68 60 5 22 87 + +90 32 41 39 6 +36 78 67 24 50 +55 72 52 75 44 +87 15 92 31 58 +83 89 68 19 43 + +99 44 53 68 25 +71 67 16 19 36 +35 58 14 86 48 +88 18 61 24 23 +87 9 91 37 15 + +37 5 63 68 28 +41 50 76 99 64 +34 92 78 94 71 +11 96 97 42 58 +33 45 0 93 48 + +33 68 9 12 81 +60 98 28 8 99 +14 17 6 82 15 +57 69 43 38 29 +47 84 76 22 18 + +79 70 92 38 47 +12 82 98 46 0 +76 15 53 59 97 +18 52 49 29 96 +44 64 68 89 24 + +95 14 17 27 42 +55 43 57 29 25 +34 73 86 50 16 +69 37 75 63 39 +78 79 3 4 30 + +27 31 15 92 46 +36 23 72 40 50 +51 99 55 89 21 +12 70 84 63 85 +78 88 77 75 0 + +15 67 40 39 28 + 9 79 22 52 75 +96 65 86 98 14 +97 87 44 84 68 +36 26 89 43 27 + +79 59 48 27 36 +85 92 93 76 24 + 2 25 7 42 90 +23 29 74 35 86 +58 60 31 75 57 + +10 43 83 75 8 +88 12 38 30 9 +60 67 59 76 6 +55 45 74 34 25 +97 49 65 96 69 + +59 86 15 3 19 +89 4 74 61 23 +52 98 8 79 39 +95 17 22 14 51 +50 18 94 30 84 + +19 63 58 72 67 +35 93 29 91 0 +39 26 43 84 21 +70 42 2 53 12 +59 99 8 1 86 + +23 86 34 22 65 +71 10 16 50 91 +66 89 49 81 43 +40 7 26 75 61 +62 59 2 46 95 + +24 21 0 49 25 +92 42 48 12 7 +81 93 59 68 3 +14 23 63 39 29 +35 43 6 44 89 + +67 74 95 34 10 +39 90 59 44 51 +17 16 97 24 62 +20 54 76 63 88 +87 66 14 78 82 + +96 86 67 59 79 +66 3 30 77 71 + 2 91 99 82 31 +48 65 75 98 53 +63 54 64 76 1 + +85 96 40 98 24 +16 20 10 23 17 +79 59 53 42 65 +67 2 5 80 75 +62 38 19 74 73 + +43 10 79 92 8 +52 36 4 5 67 +56 29 33 24 97 +85 17 53 75 65 +62 64 1 21 83 + +93 92 79 17 12 +40 88 6 82 34 +90 96 53 25 43 +14 62 54 10 39 +49 68 41 16 44 + +67 99 24 58 76 +43 53 59 54 51 +47 6 61 8 2 +80 68 90 14 4 +29 46 94 89 50 + +14 45 19 33 43 + 6 55 4 31 80 +51 2 69 68 61 +71 70 79 91 93 +66 18 54 13 87 + + 8 45 61 54 30 +85 16 19 82 37 +56 39 11 47 4 +74 70 10 60 91 +21 63 95 53 72 + +71 21 63 86 27 +53 52 40 23 81 + 2 47 92 68 15 +46 45 31 8 1 +34 80 37 11 69 + +96 0 15 90 66 +65 43 92 83 18 + 3 47 19 8 32 +71 26 42 34 28 +62 99 55 5 12 + +37 99 30 21 3 +63 18 68 47 27 +57 0 65 85 20 + 7 58 40 92 43 +15 19 5 4 53 + +46 16 45 95 68 + 6 44 31 47 73 +84 82 71 75 94 +26 25 17 32 49 +18 96 13 58 9 + +71 36 13 68 10 +84 7 60 79 41 + 1 83 43 81 97 +90 53 80 19 38 +48 25 32 42 29 + +37 68 86 44 78 +87 67 77 70 60 +45 34 27 15 47 +12 21 13 55 26 +81 41 63 40 74 + +24 50 93 94 57 +99 4 56 5 28 +42 31 22 6 76 +90 89 16 49 59 + 9 7 43 71 54 + +69 75 94 38 46 +52 64 50 72 42 +76 63 13 60 10 +99 80 43 33 17 +25 31 4 89 22 + +88 57 22 66 34 +85 16 87 95 59 +73 2 46 5 29 +25 69 53 6 14 +96 77 19 91 43 + +46 99 52 47 76 +89 53 24 13 59 +45 5 1 30 19 +68 25 22 10 73 +42 27 31 0 94 + +42 44 98 89 87 +65 10 80 56 41 + 3 35 95 48 43 +85 97 83 12 94 +50 38 93 47 17 + +16 73 18 81 89 + 6 48 54 93 19 +35 52 88 49 31 +43 79 83 14 28 +50 62 98 26 22 + +38 47 7 20 35 +45 76 63 96 24 +98 53 2 87 80 +83 86 92 48 1 +73 60 26 94 6 + +80 50 29 53 92 +66 90 79 98 46 +40 21 58 38 60 +35 13 72 28 6 +48 76 51 96 12 + +79 80 24 37 51 +86 70 1 22 71 +52 69 10 83 13 +12 40 3 0 30 +46 50 48 76 5 diff --git a/2021/day-04/solution.js b/2021/day-04/solution.js new file mode 100644 index 0000000..1339e17 --- /dev/null +++ b/2021/day-04/solution.js @@ -0,0 +1,102 @@ +const fs = require('fs') +const path = require('path') +const filePath = path.join(__dirname, 'input.txt') +const { linesToArray, parseData } = require('../../2018/inputParser') +const { markBoard, checkWinner, scoreBoard } = require('./bingo') + +fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { + if (err) throw err + + initData = linesToArray(initData.trim()) + + const resetInput = () => { + // Deep copy to ensure we aren't mutating the original data + const data = JSON.parse(JSON.stringify(initData)) + + // split up data + const draws = parseData(data.shift()) + const boards = [] + for (let x = 0; x < data.length; x = x + 5) { + boards.push( + data.slice(x, x + 5).map(parseData) + ) + } + + return { + boards, + draws + } + } + + const part1 = () => { + const data = resetInput() + + let winner = false + let draw = -1 + while (winner === false && draw < data.draws.length) { + // next draw + draw++ + + // Mark each board that has the number + console.debug(`Checking draw ${data.draws[draw]}`) + data.boards = data.boards.map((board) => { + return markBoard(board, data.draws[draw]) + }) + + // Check for a winner + data.boards.forEach((board, idx) => { + if (checkWinner(board) === 'winner') { + console.debug(`Board ${idx} is the winner`) + console.debug(data.boards[idx]) + winner = idx + } + }) + } + + // winner found + console.debug(`Score is ${scoreBoard(data.boards[winner])}`) + return scoreBoard(data.boards[winner]) * data.draws[draw] + } + + const part2 = () => { + const data = resetInput() + + let draw = -1 + let lastWin = [] + let lastDraw = 0 + + while (data.boards.length >= 1 && draw < data.draws.length) { + // next draw + draw++ + + // Mark each board that has the number + console.debug(`Checking draw ${data.draws[draw]}`) + data.boards = data.boards.map((board) => { + return markBoard(board, data.draws[draw]) + }) + + // Filter out any winners + data.boards = data.boards.filter((board) => { + if (checkWinner(board) === 'winner') { + lastWin = board + lastDraw = data.draws[draw] + return false + } else { + return true + } + }) + } + + // last winner found + console.debug(`Score is ${scoreBoard(lastWin)} on draw ${lastDraw}`) + return scoreBoard(lastWin) * lastDraw + } + const answers = [] + answers.push(part1()) + answers.push(part2()) + + answers.forEach((ans, idx) => { + console.info(`-- Part ${idx + 1} --`) + console.info(`Answer: ${ans}`) + }) +}) diff --git a/2021/day-05/index.js b/2021/day-05/index.js new file mode 100644 index 0000000..af7e035 --- /dev/null +++ b/2021/day-05/index.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-unused-vars +const console = require('../helpers') +require('./solution') diff --git a/2021/day-05/input.txt b/2021/day-05/input.txt new file mode 100644 index 0000000..d6a5213 --- /dev/null +++ b/2021/day-05/input.txt @@ -0,0 +1,500 @@ +456,846 -> 221,846 +980,926 -> 73,19 +682,930 -> 562,930 +766,592 -> 274,100 +247,685 -> 247,21 +106,800 -> 635,800 +953,340 -> 135,340 +293,223 -> 293,12 +454,196 -> 454,463 +886,766 -> 164,766 +592,590 -> 192,590 +436,982 -> 436,545 +731,571 -> 420,260 +741,11 -> 466,11 +727,541 -> 579,541 +341,553 -> 25,553 +942,470 -> 942,196 +203,600 -> 203,647 +965,595 -> 949,611 +554,306 -> 554,401 +902,438 -> 902,728 +864,609 -> 525,270 +187,790 -> 187,323 +956,950 -> 427,950 +847,554 -> 422,554 +935,900 -> 701,900 +192,854 -> 866,180 +512,946 -> 543,915 +978,979 -> 491,979 +708,61 -> 708,878 +738,508 -> 282,52 +23,25 -> 841,843 +204,750 -> 204,797 +703,500 -> 703,419 +14,311 -> 694,311 +646,301 -> 785,301 +397,168 -> 439,168 +680,931 -> 561,812 +540,448 -> 90,448 +706,668 -> 91,53 +848,319 -> 318,319 +198,948 -> 198,307 +686,58 -> 686,541 +867,234 -> 867,498 +134,125 -> 134,688 +824,566 -> 53,566 +437,167 -> 276,167 +94,65 -> 638,609 +36,971 -> 971,36 +494,330 -> 494,197 +920,438 -> 920,364 +698,84 -> 49,733 +59,842 -> 59,876 +328,577 -> 328,677 +757,701 -> 134,78 +466,274 -> 135,605 +81,925 -> 988,18 +40,142 -> 882,984 +50,96 -> 882,928 +782,47 -> 782,427 +247,599 -> 24,599 +112,812 -> 191,733 +487,198 -> 144,198 +327,663 -> 327,756 +117,76 -> 688,76 +530,71 -> 530,958 +558,602 -> 671,489 +677,830 -> 677,556 +529,669 -> 349,669 +336,966 -> 341,971 +20,31 -> 851,862 +423,880 -> 423,573 +521,657 -> 552,657 +412,822 -> 18,428 +423,311 -> 423,105 +381,614 -> 705,614 +521,248 -> 394,121 +286,47 -> 286,403 +286,27 -> 711,452 +347,61 -> 489,61 +760,454 -> 760,954 +746,573 -> 911,573 +839,933 -> 839,776 +124,815 -> 290,649 +577,848 -> 419,848 +393,206 -> 410,206 +364,755 -> 881,755 +788,68 -> 788,215 +94,798 -> 192,798 +292,250 -> 453,250 +601,545 -> 293,237 +438,923 -> 438,655 +70,757 -> 887,757 +184,402 -> 818,402 +586,49 -> 103,49 +202,315 -> 735,315 +534,504 -> 534,523 +367,236 -> 367,736 +24,163 -> 24,240 +185,426 -> 634,875 +485,189 -> 39,189 +556,30 -> 374,30 +969,821 -> 676,528 +254,435 -> 254,43 +290,615 -> 741,164 +345,601 -> 120,826 +224,641 -> 887,641 +190,716 -> 581,325 +552,646 -> 552,393 +413,177 -> 413,103 +397,900 -> 360,900 +138,980 -> 138,55 +909,891 -> 909,593 +926,986 -> 79,139 +954,67 -> 53,968 +180,30 -> 595,30 +823,165 -> 823,660 +285,176 -> 375,176 +915,826 -> 184,95 +735,230 -> 667,230 +934,865 -> 917,865 +48,602 -> 737,602 +477,319 -> 385,411 +981,17 -> 11,987 +458,401 -> 24,401 +118,415 -> 849,415 +176,678 -> 176,852 +567,753 -> 567,37 +285,868 -> 830,323 +555,623 -> 822,623 +522,546 -> 674,546 +880,21 -> 23,878 +591,103 -> 591,407 +434,64 -> 434,401 +245,968 -> 275,968 +726,510 -> 450,786 +768,366 -> 768,738 +488,745 -> 488,94 +675,674 -> 675,705 +618,237 -> 265,237 +802,709 -> 802,59 +144,696 -> 144,542 +547,381 -> 547,799 +78,667 -> 78,916 +409,271 -> 302,271 +294,694 -> 938,50 +140,571 -> 97,571 +682,875 -> 682,534 +748,816 -> 748,183 +84,622 -> 84,258 +485,696 -> 582,599 +909,233 -> 954,233 +203,711 -> 203,350 +335,904 -> 455,904 +578,778 -> 578,21 +830,954 -> 902,954 +78,252 -> 78,682 +920,220 -> 684,220 +309,301 -> 104,301 +270,795 -> 270,919 +906,479 -> 304,479 +627,164 -> 627,986 +122,960 -> 915,167 +664,916 -> 770,810 +692,810 -> 826,810 +981,951 -> 192,162 +183,423 -> 809,423 +632,464 -> 567,464 +94,266 -> 94,587 +261,770 -> 569,770 +51,403 -> 466,818 +631,645 -> 187,645 +141,238 -> 141,145 +357,21 -> 173,21 +138,248 -> 839,949 +889,957 -> 807,957 +399,431 -> 105,725 +548,331 -> 548,821 +790,844 -> 43,97 +675,671 -> 221,671 +874,143 -> 620,397 +205,435 -> 205,546 +521,434 -> 822,133 +141,86 -> 257,86 +427,28 -> 290,165 +49,694 -> 567,694 +846,344 -> 266,924 +425,910 -> 433,918 +956,498 -> 485,27 +798,498 -> 798,634 +879,13 -> 766,126 +737,475 -> 737,425 +338,473 -> 425,386 +510,615 -> 214,319 +758,415 -> 758,490 +969,208 -> 239,938 +917,188 -> 917,528 +34,820 -> 806,820 +85,633 -> 857,633 +262,355 -> 262,748 +373,784 -> 971,186 +146,577 -> 60,663 +613,570 -> 613,199 +300,319 -> 300,108 +764,171 -> 764,17 +555,921 -> 555,825 +241,197 -> 770,197 +600,832 -> 600,807 +934,987 -> 20,73 +960,730 -> 837,730 +976,50 -> 46,980 +829,834 -> 153,158 +785,835 -> 785,58 +586,633 -> 689,736 +804,250 -> 348,706 +226,539 -> 16,539 +411,940 -> 98,940 +289,589 -> 893,589 +738,616 -> 738,55 +225,54 -> 542,54 +793,246 -> 303,736 +332,752 -> 984,100 +413,18 -> 839,444 +840,122 -> 840,233 +989,970 -> 215,196 +329,361 -> 573,605 +242,537 -> 242,619 +943,898 -> 943,535 +469,865 -> 501,833 +226,717 -> 196,687 +819,803 -> 712,803 +532,663 -> 532,672 +61,931 -> 940,52 +623,218 -> 274,567 +281,326 -> 281,790 +815,176 -> 679,176 +790,862 -> 942,710 +18,771 -> 18,514 +479,377 -> 309,377 +704,402 -> 704,150 +961,335 -> 492,335 +745,829 -> 745,477 +556,543 -> 771,543 +832,336 -> 917,251 +742,755 -> 742,174 +206,735 -> 493,735 +151,216 -> 312,55 +445,157 -> 615,157 +781,143 -> 781,76 +833,717 -> 514,398 +357,14 -> 357,36 +771,405 -> 771,422 +662,886 -> 169,886 +689,990 -> 22,990 +680,445 -> 379,445 +92,369 -> 502,779 +64,948 -> 64,363 +295,957 -> 976,276 +113,920 -> 634,399 +542,662 -> 305,899 +566,514 -> 566,645 +528,106 -> 549,106 +205,367 -> 821,367 +313,105 -> 313,928 +532,177 -> 532,664 +862,773 -> 905,816 +800,796 -> 911,796 +870,80 -> 11,939 +188,900 -> 154,900 +420,509 -> 520,609 +540,863 -> 28,863 +31,72 -> 78,72 +823,648 -> 503,648 +879,252 -> 606,252 +677,117 -> 677,507 +743,303 -> 196,850 +220,491 -> 220,891 +216,815 -> 577,815 +540,819 -> 745,819 +152,721 -> 382,721 +280,745 -> 985,745 +479,367 -> 358,488 +913,413 -> 649,413 +40,678 -> 817,678 +467,533 -> 467,214 +132,68 -> 843,779 +519,109 -> 669,259 +619,791 -> 221,791 +114,622 -> 628,622 +951,636 -> 866,636 +172,569 -> 775,569 +244,972 -> 173,972 +283,64 -> 739,520 +68,604 -> 68,156 +529,30 -> 529,925 +813,883 -> 137,883 +893,231 -> 629,231 +673,658 -> 673,389 +725,899 -> 218,899 +317,318 -> 105,318 +82,706 -> 100,688 +222,227 -> 440,227 +810,371 -> 810,985 +414,321 -> 289,446 +901,158 -> 260,799 +198,967 -> 717,448 +928,454 -> 875,454 +974,437 -> 974,764 +657,13 -> 760,13 +498,966 -> 976,966 +66,104 -> 66,15 +773,569 -> 980,362 +420,496 -> 403,513 +57,920 -> 85,920 +879,551 -> 879,662 +98,395 -> 98,398 +483,685 -> 483,55 +222,935 -> 586,935 +89,926 -> 807,208 +744,160 -> 744,462 +588,973 -> 588,548 +312,572 -> 38,298 +27,131 -> 552,656 +591,935 -> 591,86 +907,478 -> 907,279 +981,75 -> 981,972 +316,947 -> 935,947 +906,38 -> 906,216 +374,521 -> 345,550 +579,29 -> 579,107 +444,636 -> 444,557 +458,608 -> 830,980 +479,839 -> 155,515 +766,600 -> 766,71 +976,965 -> 31,20 +928,49 -> 269,708 +787,238 -> 787,983 +583,742 -> 112,742 +966,268 -> 554,680 +671,354 -> 671,966 +274,340 -> 274,894 +673,185 -> 607,185 +73,171 -> 874,171 +861,526 -> 861,410 +739,591 -> 739,138 +209,355 -> 209,146 +286,501 -> 887,501 +495,902 -> 700,902 +192,889 -> 821,260 +400,21 -> 154,21 +861,301 -> 325,301 +552,990 -> 511,990 +908,21 -> 11,918 +127,724 -> 821,30 +935,46 -> 170,811 +947,91 -> 374,91 +625,420 -> 265,60 +214,228 -> 546,228 +375,547 -> 715,887 +516,350 -> 870,350 +610,138 -> 665,193 +214,621 -> 678,621 +497,248 -> 600,145 +549,558 -> 576,558 +364,537 -> 364,312 +840,324 -> 310,854 +441,945 -> 441,458 +459,531 -> 459,100 +937,113 -> 150,900 +277,405 -> 259,405 +409,527 -> 409,359 +534,766 -> 534,740 +534,934 -> 681,934 +456,419 -> 83,419 +871,986 -> 873,986 +14,59 -> 916,961 +911,963 -> 971,963 +25,325 -> 139,211 +937,184 -> 354,767 +460,416 -> 289,245 +193,171 -> 861,839 +840,299 -> 840,911 +531,45 -> 531,619 +599,315 -> 455,315 +455,97 -> 455,811 +38,748 -> 392,748 +841,79 -> 841,88 +105,571 -> 105,545 +801,458 -> 344,458 +491,535 -> 558,535 +835,814 -> 223,202 +563,85 -> 405,85 +410,396 -> 600,396 +273,670 -> 818,125 +671,647 -> 817,647 +46,892 -> 678,260 +456,736 -> 110,736 +962,941 -> 619,598 +388,406 -> 53,71 +558,895 -> 227,564 +944,182 -> 807,319 +484,898 -> 59,473 +808,214 -> 488,534 +451,679 -> 155,383 +858,931 -> 381,931 +723,377 -> 723,281 +694,283 -> 182,795 +385,191 -> 320,256 +33,380 -> 584,931 +480,91 -> 817,91 +677,91 -> 677,126 +291,651 -> 760,182 +832,962 -> 153,283 +38,60 -> 479,501 +249,350 -> 789,350 +603,341 -> 266,678 +52,303 -> 52,102 +911,201 -> 559,201 +46,210 -> 46,275 +960,212 -> 554,212 +375,374 -> 169,580 +10,10 -> 989,989 +844,140 -> 40,944 +916,408 -> 916,815 +834,401 -> 834,169 +553,479 -> 784,248 +543,452 -> 543,848 +854,910 -> 334,390 +685,491 -> 793,491 +552,943 -> 709,943 +723,367 -> 124,367 +95,55 -> 881,841 +155,267 -> 573,267 +59,357 -> 84,357 +218,435 -> 218,344 +491,584 -> 491,649 +676,445 -> 676,333 +361,618 -> 783,618 +220,295 -> 220,267 +668,758 -> 299,389 +965,845 -> 674,845 +285,603 -> 47,603 +853,417 -> 853,757 +859,906 -> 856,906 +55,364 -> 753,364 +893,474 -> 978,474 +602,32 -> 58,576 +171,445 -> 96,370 +214,592 -> 214,286 +400,946 -> 745,946 +559,37 -> 112,484 +624,510 -> 90,510 +329,714 -> 329,850 +458,287 -> 657,287 +99,385 -> 99,949 +50,736 -> 719,67 +273,195 -> 273,306 +490,902 -> 490,798 +619,131 -> 921,131 +266,652 -> 266,730 +745,661 -> 745,555 +311,878 -> 311,679 +491,982 -> 643,830 +735,875 -> 816,875 +936,353 -> 936,529 +792,467 -> 565,467 +141,140 -> 141,988 +98,171 -> 414,487 +257,259 -> 257,484 +24,41 -> 969,986 +302,453 -> 223,453 +807,363 -> 492,678 +823,22 -> 835,10 +301,94 -> 399,94 +946,110 -> 248,808 +983,985 -> 21,23 +510,145 -> 510,58 +13,661 -> 13,639 +218,260 -> 218,54 +475,846 -> 475,770 +458,644 -> 458,529 +912,934 -> 912,136 +152,823 -> 550,823 +136,470 -> 443,470 +253,871 -> 905,219 +765,212 -> 793,240 +11,402 -> 11,42 +348,813 -> 348,768 +368,321 -> 823,776 +343,495 -> 343,809 +117,616 -> 117,273 +92,92 -> 732,92 +914,31 -> 28,917 +259,944 -> 214,944 +630,759 -> 462,759 +134,653 -> 134,610 +14,989 -> 988,15 +139,181 -> 139,451 +598,636 -> 598,442 +263,42 -> 686,465 diff --git a/2021/day-05/solution.js b/2021/day-05/solution.js new file mode 100644 index 0000000..1290e5e --- /dev/null +++ b/2021/day-05/solution.js @@ -0,0 +1,53 @@ +const fs = require('fs') +const path = require('path') +const filePath = path.join(__dirname, 'input.txt') +const { parseLines, chartLine, countIntersections } = require('./vents') + +fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { + if (err) throw err + + initData = parseLines(initData.trim()) + + const resetInput = () => { + // Deep copy to ensure we aren't mutating the original data + return JSON.parse(JSON.stringify(initData)) + } + + const task = (supportDiagonals) => { + const data = resetInput() + + // Allocate map + const max = data.reduce((max, curr) => { + max[0] = Math.max(max[0], curr[0], curr[2]) // find the maximum X value + max[1] = Math.max(max[1], curr[1], curr[3]) // find the maximum Y value + return max + }, [0, 0]) + + let map = [...new Array(max[1] + 1)].map(() => { + return [...new Array(max[0] + 1)].map(() => 0) + }) + + data.forEach((line) => { + map = chartLine(map, ...line, supportDiagonals) + }) + + return countIntersections(map, 2) + } + + const part1 = () => { + return task(false) + } + + const part2 = () => { + return task(true) + } + + const answers = [] + answers.push(part1()) + answers.push(part2()) + + answers.forEach((ans, idx) => { + console.info(`-- Part ${idx + 1} --`) + console.info(`Answer: ${ans}`) + }) +}) diff --git a/2021/day-05/vents.js b/2021/day-05/vents.js new file mode 100644 index 0000000..33e7dc5 --- /dev/null +++ b/2021/day-05/vents.js @@ -0,0 +1,92 @@ +/** + * + * @param {*} data Existing coordinate data + * @param {*} x1 start of line horizontal point + * @param {*} y1 start of line vertical point + * @param {*} x2 end of line horizontal point + * @param {*} y2 end of line vertical point + * @returns + */ +const chartLine = (data, x1, y1, x2, y2, allowDiaganol = false) => { + let x = x1 + let y = y1 + if (y1 === y2) { + // chart horizontal line + console.debug(`Drawing horizontal line ${x1},${y1} to ${x2},${y2}`) + const xDir = (x2 > x1) ? 1 : -1 + while (x !== x2) { + data[y][x]++ + x += xDir + } + data[y][x]++ // coordinates are inclusive + } else if (x1 === x2) { + // chart vertical line + console.debug(`Drawing vertical line ${x1},${y1} to ${x2},${y2}`) + const yDir = (y2 > y1) ? 1 : -1 + while (y !== y2) { + data[y][x]++ + y += yDir + } + data[y][x]++ // coordinates are inclusive + } else if (allowDiaganol) { + // chart diagonal line + console.debug(`Drawing diagonal line ${x1},${y1} to ${x2},${y2}`) + const xDir = (x2 > x1) ? 1 : -1 + const yDir = (y2 > y1) ? 1 : -1 + while (x !== x2 && y !== y2) { + data[y][x]++ + x += xDir + y += yDir + } + data[y][x]++ // coordinates are inclusive + } else { + console.debug(`Skipping diagonal line ${x1},${y1} to ${x2},${y2}`) + } + return data +} + +/** + * Count the number of points with more than [threshold] intersecting lines + * @param {*} data + * @param {*} threshold + * @returns + */ +const countIntersections = (data, threshold) => { + return data.reduce((total, row) => { + total += row.filter((cell) => (cell >= threshold)).length + return total + }, 0) +} + +/** + * Creates a visible map from the data + * @param {*} data + * @returns string + */ +const render = (data) => { + return data + .map((row) => row.join('')) + .join('\n') + .replace(/0/gi, '.') +} + +/** + * Parses the provided data rules into useable lines + * @param string data + * @returns Array + */ +const parseLines = (data) => { + return data.split('\n') + .map( + (row) => row.replace(' -> ', ',') + .split(',') + .map((val) => parseInt(val)) + ) +} + +module.exports = { + render, + chartLine, + countIntersections, + parseLines +} diff --git a/2021/day-05/vents.test.js b/2021/day-05/vents.test.js new file mode 100644 index 0000000..6a16859 --- /dev/null +++ b/2021/day-05/vents.test.js @@ -0,0 +1,113 @@ +/* eslint-env mocha */ +const { expect } = require('chai') +const { render, chartLine, parseLines, countIntersections } = require('./vents') + +const testData = `0,9 -> 5,9 +8,0 -> 0,8 +9,4 -> 3,4 +2,2 -> 2,1 +7,0 -> 7,4 +6,4 -> 2,0 +0,9 -> 2,9 +3,4 -> 1,4 +0,0 -> 8,8 +5,5 -> 8,2` + +const sampleMap = `.......1.. +..1....1.. +..1....1.. +.......1.. +.112111211 +.......... +.......... +.......... +.......... +222111....` + +const sampleDiagonalMap = `1.1....11. +.111...2.. +..2.1.111. +...1.2.2.. +.112313211 +...1.2.... +..1...1... +.1.....1.. +1.......1. +222111....` + +const parsedTestData = parseLines(testData) + +describe('--- Day 5: Hydrothermal Venture ---', () => { + describe('Part 1', () => { + describe('render()', () => { + it('displays a visual map of the vents', () => { + expect(render([[0, 0, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 1, 1, 2, 1, 1, 1, 2, 1, 1], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [2, 2, 2, 1, 1, 1, 0, 0, 0, 0]])) + .to.equal(sampleMap) + }) + }) + describe('chartLine()', () => { + it('charts a line between two points', () => { + // 10x10 empty grid + let data = [...new Array(10)].map(() => { + return [...new Array(10)].map(() => 0) + }) + // Map some horizontal and vertical lines + data = chartLine(data, 0, 9, 5, 9) + data = chartLine(data, 9, 4, 3, 4) + data = chartLine(data, 2, 2, 2, 1) + data = chartLine(data, 7, 0, 7, 4) + data = chartLine(data, 0, 9, 2, 9) + data = chartLine(data, 3, 4, 1, 4) + expect(render(data)).to.equal(sampleMap) + }) + it('skips diagonal lines', () => { + // 10x10 empty grid + let data = [...new Array(10)].map(() => { + return [...new Array(10)].map(() => 0) + }) + // Map some lines + parsedTestData.forEach((row) => { + data = chartLine(data, ...row) + }) + expect(render(data)).to.equal(sampleMap) + }) + }) + describe('countIntersections()', () => { + it('counts how many intersections exist of (n) lines or more', () => { + // 10x10 empty grid + let data = [...new Array(10)].map(() => { + return [...new Array(10)].map(() => 0) + }) + // Map some lines + parsedTestData.forEach((row) => { + data = chartLine(data, ...row) + }) + expect(countIntersections(data, 2)).to.equal(5) + }) + }) + }) + describe('Part 2', () => { + describe('chartLine()', () => { + it('includes diagonal lines when specified', () => { + // 10x10 empty grid + let data = [...new Array(10)].map(() => { + return [...new Array(10)].map(() => 0) + }) + // Map some lines + parsedTestData.forEach((row) => { + data = chartLine(data, ...row, true) + }) + expect(render(data)).to.equal(sampleDiagonalMap) + }) + }) + }) +}) diff --git a/README.md b/README.md index 84880b0..a5965c8 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ ## Status ### 2020 -![](https://img.shields.io/badge/day%20📅-0-blue) -![](https://img.shields.io/badge/stars%20⭐-0-yellow) -![](https://img.shields.io/badge/days%20completed-0-red) +![](https://img.shields.io/badge/day%20📅-14-blue) +![](https://img.shields.io/badge/stars%20⭐-6-yellow) +![](https://img.shields.io/badge/days%20completed-3-red) ## Start a boilerplate for a new day `npm run new` diff --git a/index.js b/index.js index b752549..ed39a00 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -require('./2021/day-03/solution') +require('./2021/day-05/solution') pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy