From 7f8a13f2706ed58424e8600cc86f18d762d493b5 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Mon, 13 Dec 2021 22:34:52 -0800 Subject: [PATCH 1/7] feat(2021-day-04): find the first board with a bingo --- 2021/day-04/bingo.js | 76 +++++ 2021/day-04/bingo.test.js | 133 +++++++++ 2021/day-04/index.js | 3 + 2021/day-04/input.txt | 601 ++++++++++++++++++++++++++++++++++++++ 2021/day-04/solution.js | 74 +++++ index.js | 2 +- 6 files changed, 888 insertions(+), 1 deletion(-) create mode 100644 2021/day-04/bingo.js create mode 100644 2021/day-04/bingo.test.js create mode 100644 2021/day-04/index.js create mode 100644 2021/day-04/input.txt create mode 100644 2021/day-04/solution.js diff --git a/2021/day-04/bingo.js b/2021/day-04/bingo.js new file mode 100644 index 0000000..5f3657c --- /dev/null +++ b/2021/day-04/bingo.js @@ -0,0 +1,76 @@ +const boards = [] + +const callNumber = (called) => { + for (let x = 0; x < boards.length; x++) { + markBoard(x, called) + if (checkWinner(x) === 'winner') { + console.debug(`Board ${x} is the winner`) + return x + } + } +} + +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 = { + callNumber, + 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..90cb97e --- /dev/null +++ b/2021/day-04/bingo.test.js @@ -0,0 +1,133 @@ +/* eslint-env mocha */ +const { expect } = require('chai') +const { callNumber, scoreBoard, checkWinner, markBoard } = require('./bingo') +const { parseData } = 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(testData)) + +// split up data +const testDraws = parseData(data.shift()) +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) + }) + it.skip('can be used in a loop to find', () => { + // callNumber(7) + // callNumber(4) + // callNumber(9) + // callNumber(5) + // callNumber(11) + // for(var x = 0; x < testBoards) + // expect(boards[0]).to.deep.equal(board0) + // expect(boards[1]).to.deep.equal(board1) + // expect(boards[2]).to.deep.equal(board2) + // callNumber(17) + // callNumber(23) + // callNumber(2) + // callNumber(0) + // callNumber(14) + // callNumber(21) + // expect(boards[0]).to.deep.equal(board0) + // expect(boards[1]).to.deep.equal(board1) + // expect(boards[2]).to.deep.equal(board2) + }) + it.skip('identifies the winner', () => { + expect(callNumber(24)).to.equal(3) + }) + }) + describe('findWinner()', () => { + it.skip('loops through the boards and checks for a winner', () => { + + }) + }) + 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..375f0ad --- /dev/null +++ b/2021/day-04/solution.js @@ -0,0 +1,74 @@ +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() + // console.debug(data) + return 'No answer yet' + } + const answers = [] + answers.push(part1()) + answers.push(part2()) + + answers.forEach((ans, idx) => { + console.info(`-- Part ${idx + 1} --`) + console.info(`Answer: ${ans}`) + }) +}) diff --git a/index.js b/index.js index b752549..95257dc 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -require('./2021/day-03/solution') +require('./2021/day-04/solution') From 5ea8fbb600637393e0dfe4650d7eeff915d1f075 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Mon, 13 Dec 2021 22:55:51 -0800 Subject: [PATCH 2/7] feat(2021-day-04): find the last board that will score a bingo --- 2021/day-04/bingo.js | 13 ------------- 2021/day-04/bingo.test.js | 35 ++++------------------------------- 2021/day-04/solution.js | 34 +++++++++++++++++++++++++++++++--- 3 files changed, 35 insertions(+), 47 deletions(-) diff --git a/2021/day-04/bingo.js b/2021/day-04/bingo.js index 5f3657c..b6a26c0 100644 --- a/2021/day-04/bingo.js +++ b/2021/day-04/bingo.js @@ -1,15 +1,3 @@ -const boards = [] - -const callNumber = (called) => { - for (let x = 0; x < boards.length; x++) { - markBoard(x, called) - if (checkWinner(x) === 'winner') { - console.debug(`Board ${x} is the winner`) - return x - } - } -} - const markBoard = (board, called) => { for (let x = 0; x < 5; x++) { for (let y = 0; y < 5; y++) { @@ -69,7 +57,6 @@ const scoreBoard = (board) => { } module.exports = { - callNumber, scoreBoard, checkWinner, markBoard diff --git a/2021/day-04/bingo.test.js b/2021/day-04/bingo.test.js index 90cb97e..cc77f84 100644 --- a/2021/day-04/bingo.test.js +++ b/2021/day-04/bingo.test.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ const { expect } = require('chai') -const { callNumber, scoreBoard, checkWinner, markBoard } = require('./bingo') -const { parseData } = require('../../2018/inputParser') +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 @@ -25,10 +25,11 @@ const testData = ` 2 0 12 3 7 ` // Deep copy to ensure we aren't mutating the original data -const data = JSON.parse(JSON.stringify(testData)) +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( @@ -56,34 +57,6 @@ describe('--- Day 4: Giant Squid ---', () => { ] expect(markBoard(board, 5)).to.deep.equal(expected) }) - it.skip('can be used in a loop to find', () => { - // callNumber(7) - // callNumber(4) - // callNumber(9) - // callNumber(5) - // callNumber(11) - // for(var x = 0; x < testBoards) - // expect(boards[0]).to.deep.equal(board0) - // expect(boards[1]).to.deep.equal(board1) - // expect(boards[2]).to.deep.equal(board2) - // callNumber(17) - // callNumber(23) - // callNumber(2) - // callNumber(0) - // callNumber(14) - // callNumber(21) - // expect(boards[0]).to.deep.equal(board0) - // expect(boards[1]).to.deep.equal(board1) - // expect(boards[2]).to.deep.equal(board2) - }) - it.skip('identifies the winner', () => { - expect(callNumber(24)).to.equal(3) - }) - }) - describe('findWinner()', () => { - it.skip('loops through the boards and checks for a winner', () => { - - }) }) describe('checkWinner()', () => { it('checks to see if a board has a horizontal bingo', () => { diff --git a/2021/day-04/solution.js b/2021/day-04/solution.js index 375f0ad..1339e17 100644 --- a/2021/day-04/solution.js +++ b/2021/day-04/solution.js @@ -59,9 +59,37 @@ fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { } const part2 = () => { - // const data = resetInput() - // console.debug(data) - return 'No answer yet' + 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()) From a20facaa15c3f98b263416d2ac081549f0ed88f7 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Tue, 14 Dec 2021 01:39:16 -0800 Subject: [PATCH 3/7] feat(2021-day-05): map orthagonal lines for hydrothermal vents --- 2021/day-05/vents.js | 67 +++++++++++++++++++++++++++++++++++ 2021/day-05/vents.test.js | 74 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 2021/day-05/vents.js create mode 100644 2021/day-05/vents.test.js diff --git a/2021/day-05/vents.js b/2021/day-05/vents.js new file mode 100644 index 0000000..2f04d93 --- /dev/null +++ b/2021/day-05/vents.js @@ -0,0 +1,67 @@ +/** + * + * @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) => { + 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 { + console.debug(`Skipping diagonal line ${x1},${y1} to ${x2},${y2}`) + } + return data +} + +/** + * 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, + parseLines +} diff --git a/2021/day-05/vents.test.js b/2021/day-05/vents.test.js new file mode 100644 index 0000000..5159fdd --- /dev/null +++ b/2021/day-05/vents.test.js @@ -0,0 +1,74 @@ +/* eslint-env mocha */ +const { expect } = require('chai') +const { render, chartLine, parseLines } = 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 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) + }) + }) +}) From 1a867ccc0a4b0a706ac04729175fd578bde188f7 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Tue, 14 Dec 2021 01:49:41 -0800 Subject: [PATCH 4/7] feat(2021-day-05): count the intersections on the map that exceed a threshold of lines --- 2021/day-05/vents.js | 14 ++++++++++++++ 2021/day-05/vents.test.js | 33 +++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/2021/day-05/vents.js b/2021/day-05/vents.js index 2f04d93..282ca19 100644 --- a/2021/day-05/vents.js +++ b/2021/day-05/vents.js @@ -34,6 +34,19 @@ const chartLine = (data, x1, y1, 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 @@ -63,5 +76,6 @@ const parseLines = (data) => { module.exports = { render, chartLine, + countIntersections, parseLines } diff --git a/2021/day-05/vents.test.js b/2021/day-05/vents.test.js index 5159fdd..8b44864 100644 --- a/2021/day-05/vents.test.js +++ b/2021/day-05/vents.test.js @@ -1,6 +1,6 @@ /* eslint-env mocha */ const { expect } = require('chai') -const { render, chartLine, parseLines } = require('./vents') +const { render, chartLine, parseLines, countIntersections } = require('./vents') const testData = `0,9 -> 5,9 8,0 -> 0,8 @@ -58,17 +58,30 @@ describe('--- Day 5: Hydrothermal Venture ---', () => { 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) + 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) }) - // Map some lines - parsedTestData.forEach((row) => { - data = chartLine(data, ...row) + }) + 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) }) - expect(render(data)).to.equal(sampleMap) }) }) }) From 50f064dfd04510e316e4ca3d0dd81263686aa15b Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Tue, 14 Dec 2021 02:09:29 -0800 Subject: [PATCH 5/7] feat(2021-day-05): count orthogonal intersections on the vent map Solution for part 1 --- 2021/day-05/index.js | 3 + 2021/day-05/input.txt | 500 ++++++++++++++++++++++++++++++++++++++++ 2021/day-05/solution.js | 51 ++++ index.js | 2 +- 4 files changed, 555 insertions(+), 1 deletion(-) create mode 100644 2021/day-05/index.js create mode 100644 2021/day-05/input.txt create mode 100644 2021/day-05/solution.js 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..232d95e --- /dev/null +++ b/2021/day-05/solution.js @@ -0,0 +1,51 @@ +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 part1 = () => { + 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]) + + console.debug(max) + + let map = [...new Array(max[1] + 1)].map(() => { + return [...new Array(max[0] + 1)].map(() => 0) + }) + + data.forEach((line) => { + map = chartLine(map, ...line) + }) + + return countIntersections(map, 2) + } + + const part2 = () => { + const data = resetInput() + console.debug(data) + return 'No answer yet' + } + const answers = [] + answers.push(part1()) + answers.push(part2()) + + answers.forEach((ans, idx) => { + console.info(`-- Part ${idx + 1} --`) + console.info(`Answer: ${ans}`) + }) +}) diff --git a/index.js b/index.js index 95257dc..ed39a00 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -require('./2021/day-04/solution') +require('./2021/day-05/solution') From 6adb95e173fc40ee0d5e2f06d40747996f8c3e38 Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Tue, 14 Dec 2021 02:18:21 -0800 Subject: [PATCH 6/7] feat(2021-day-05): support charting diagonal lines on vent map --- 2021/day-05/vents.js | 13 ++++++++++++- 2021/day-05/vents.test.js | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/2021/day-05/vents.js b/2021/day-05/vents.js index 282ca19..33e7dc5 100644 --- a/2021/day-05/vents.js +++ b/2021/day-05/vents.js @@ -7,7 +7,7 @@ * @param {*} y2 end of line vertical point * @returns */ -const chartLine = (data, x1, y1, x2, y2) => { +const chartLine = (data, x1, y1, x2, y2, allowDiaganol = false) => { let x = x1 let y = y1 if (y1 === y2) { @@ -28,6 +28,17 @@ const chartLine = (data, x1, y1, x2, y2) => { 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}`) } diff --git a/2021/day-05/vents.test.js b/2021/day-05/vents.test.js index 8b44864..6a16859 100644 --- a/2021/day-05/vents.test.js +++ b/2021/day-05/vents.test.js @@ -24,6 +24,17 @@ const sampleMap = `.......1.. .......... 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 ---', () => { @@ -84,4 +95,19 @@ describe('--- Day 5: Hydrothermal Venture ---', () => { }) }) }) + 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) + }) + }) + }) }) From 9421e73e80e48f169569c0190e3d43728401496d Mon Sep 17 00:00:00 2001 From: Anthony McLin Date: Tue, 14 Dec 2021 02:23:20 -0800 Subject: [PATCH 7/7] feat(2021-day-06): count the intersections when including diagonals solves part 2 --- 2021/day-05/solution.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/2021/day-05/solution.js b/2021/day-05/solution.js index 232d95e..1290e5e 100644 --- a/2021/day-05/solution.js +++ b/2021/day-05/solution.js @@ -13,8 +13,9 @@ fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { return JSON.parse(JSON.stringify(initData)) } - const part1 = () => { + 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 @@ -22,24 +23,25 @@ fs.readFile(filePath, { encoding: 'utf8' }, (err, initData) => { return max }, [0, 0]) - console.debug(max) - let map = [...new Array(max[1] + 1)].map(() => { return [...new Array(max[0] + 1)].map(() => 0) }) data.forEach((line) => { - map = chartLine(map, ...line) + map = chartLine(map, ...line, supportDiagonals) }) return countIntersections(map, 2) } + const part1 = () => { + return task(false) + } + const part2 = () => { - const data = resetInput() - console.debug(data) - return 'No answer yet' + return task(true) } + const answers = [] answers.push(part1()) answers.push(part2())