diff --git a/2023/day-02/game.js b/2023/day-02/game.js new file mode 100644 index 0000000..37ea786 --- /dev/null +++ b/2023/day-02/game.js @@ -0,0 +1,96 @@ +const parseGame = (gameString) => { + const data = gameString.split(':') + const id = parseInt( + data[0].match(/\d+/)[0] // find the game number + ) + const draws = data[1].split(';') // split the game into draws + .map((draw) => { + const result = ['red', 'green', 'blue'] + .map((color) => { // extract count for each color + const reg = new RegExp(`\\d+(?= ${color})`) + console.debug(reg) + const val = draw.match(reg) || [0] + console.debug(`${color} ${val}`) + return parseInt(val).toString(16).padStart(2, '0') // convert to hex + }) + + return result.join('') // combine into a RGB hex color string + }) + + return { + id, + draws + } +} + +const parseHex = (hex) => { + return { + r: parseInt(hex.substring(0, 2), 16), + g: parseInt(hex.substring(2, 4), 16), + b: parseInt(hex.substring(4, 6), 16) + } +} + +const validateDraw = (draw, limit) => { + const data = parseHex(draw) + const lim = parseHex(limit) + return (data.r <= lim.r && data.g <= lim.g && data.b <= lim.b) +} + +const validateGame = (game, limit) => { + // const lim = parseHex(limit) + // const tally = game.draws.reduce((acc, draw) => { + // const drawData = parseHex(draw) + // return { + // r: acc.r + drawData.r, + // g: acc.g + drawData.g, + // b: acc.b + drawData.b + // } + // }, { r: 0, g: 0, b: 0 }) + + // const result = (tally.r <= lim.r && tally.g <= lim.g && tally.b <= lim.b) + // console.debug(`Game ${game.id} ${(result) ? 'passes' : 'fails'}`) + // if (!result) { + // console.debug(tally) + // } + + // If any draw fails, the full game fails + const result = game.draws.reduce((res, draw) => { + return (res && validateDraw(draw, limit)) + }, true) + return result +} + +const checksumGameSet = (games, limit) => { + // tally the IDs of valid games + return games.reduce((acc, game) => { + return validateGame(game, limit) ? acc + game.id : acc + }, 0) +} + +const countCubesNeeded = (game) => { + const max = game.draws.reduce((acc, draw) => { + const drawData = parseHex(draw) + return { + r: Math.max(acc.r, drawData.r), + g: Math.max(acc.g, drawData.g), + b: Math.max(acc.b, drawData.b) + } + }, { r: 0, g: 0, b: 0 }) + + return max +} + +const power = (game) => { + const needed = countCubesNeeded(game) + return needed.r * needed.g * needed.b +} + +module.exports = { + parseGame, + validateGame, + checksumGameSet, + validateDraw, + countCubesNeeded, + power +} diff --git a/2023/day-02/game.test.js b/2023/day-02/game.test.js new file mode 100644 index 0000000..f989d93 --- /dev/null +++ b/2023/day-02/game.test.js @@ -0,0 +1,228 @@ +/* eslint-env mocha */ +const { expect } = require('chai') +const { parseGame, validateGame, checksumGameSet, validateDraw, countCubesNeeded, power } = require('./game') +const { linesToArray } = require('../../2018/inputParser') +const fs = require('fs') +const path = require('path') +const filePath = path.join(__dirname, 'input.txt') + +describe('--- Day 2: Cube Conundrum ---', () => { + describe('Part 1', () => { + describe('parseGame', () => { + it('extracts a game string into a data object with RGB hex values for draws', () => { + const data = [ + 'Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green', + 'Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue', + 'Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red', + 'Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red', + 'Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green' + ] + const result = [ + { + id: 1, + draws: [ + '040003', + '010206', + '000200' + ] + }, { + id: 2, + draws: [ + '000201', + '010304', + '000101' + ] + }, { + id: 3, + draws: [ + '140806', + '040d05', + '010500' + ] + }, { + id: 4, + draws: [ + '030106', + '060300', + '0e030f' + ] + }, { + id: 5, + draws: [ + '060301', + '010202' + ] + } + ] + + data.forEach((game, idx) => { + expect(parseGame(game)).to.deep.equal(result[idx]) + }) + }) + }) + + describe('validateGame', () => { + it('checks if the game is valid given the limits', () => { + const limits = '0c0d0e' // 12 red cubes, 13 green cubes, and 14 blue cubes + const data = [ + { + id: 1, + draws: [ + '040003', + '010206', + '000200' + ] + }, { + id: 2, + draws: [ + '000201', + '010304', + '000101' + ] + }, { + id: 3, + draws: [ + '140806', + '040d05', + '010500' + ] + }, { + id: 4, + draws: [ + '030106', + '060300', + '0e030f' + ] + }, { + id: 5, + draws: [ + '060301', + '010202' + ] + } + ] + const result = [true, true, false, false, true] + data.forEach((game, idx) => { + expect(validateGame(game, limits)).to.equal(result[idx]) + }) + }) + }) + + describe('checksumGameSet', () => { + it('tallies the IDs of valid games', () => { + const limits = '0c0d0e' // 12 red cubes, 13 green cubes, and 14 blue cubes + const data = [ + { + id: 1, + draws: [ + '040003', + '010206', + '000200' + ] + }, { + id: 2, + draws: [ + '000201', + '010304', + '000101' + ] + }, { + id: 3, + draws: [ + '140806', + '040d05', + '010500' + ] + }, { + id: 4, + draws: [ + '030106', + '060300', + '0e030f' + ] + }, { + id: 5, + draws: [ + '060301', + '010202' + ] + } + ] + + expect(checksumGameSet(data, limits)).to.equal(8) + }) + }) + + describe('validateDraw', () => { + it('validates an individual draw is within limits', () => { + const limit = '0c0d0e' + expect(validateDraw('010206', limit)).to.equal(true) + expect(validateDraw('060301', limit)).to.equal(true) + expect(validateDraw('040d05', limit)).to.equal(true) + expect(validateDraw('140806', limit)).to.equal(false) // game 3 draw 1 has 20 reds + expect(validateDraw('0e030f', limit)).to.equal(false) // game 4 draw 3 has 15 blues + }) + }) + + describe.skip('integration test', () => { + let initData + before((done) => { + fs.readFile(filePath, { encoding: 'utf8' }, (err, rawData) => { + if (err) throw err + initData = linesToArray(rawData.trim()).map(parseGame) + // Deep copy to ensure we aren't mutating the original data + // data = JSON.parse(JSON.stringify(initData)) + done() + }) + }) + + it('result matches what we know about the answer', () => { + const limit = [12, 13, 14] // 12 red, 13 green, 14 blue + .map((num) => num.toString(16).padStart(2, '0')) + .join('') + + expect(checksumGameSet(initData, limit)).to.be.gt(177) // 177 is too low + expect(checksumGameSet(initData, limit)).to.be.gt(1452) // 1452 (from creating the limit in hex wrong, and assuming cubes are not returned to the bag after each draw) is too low + }) + }) + }) + + describe('Part 2', () => { + describe('countCubesNeeded', () => { + it('counts how many cubes are needed for a game', () => { + const data = [ + 'Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green', + 'Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue', + 'Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red', + 'Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red', + 'Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green' + ] + const result = [ + { r: 4, g: 2, b: 6 }, + { r: 1, g: 3, b: 4 }, + { r: 20, g: 13, b: 6 }, + { r: 14, g: 3, b: 15 }, + { r: 6, g: 3, b: 2 } + ] + data.forEach((game, idx) => { + expect(countCubesNeeded(parseGame(game))).to.deep.equal(result[idx]) + }) + }) + }) + describe('power', () => { + it('calculates the power for a game', () => { + const data = [ + 'Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green', + 'Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue', + 'Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red', + 'Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red', + 'Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green' + ] + const result = [48, 12, 1560, 630, 36] + data.forEach((game, idx) => { + expect(power(parseGame(game))).to.equal(result[idx]) + }) + }) + }) + }) +}) diff --git a/2023/day-02/index.js b/2023/day-02/index.js new file mode 100644 index 0000000..af7e035 --- /dev/null +++ b/2023/day-02/index.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-unused-vars +const console = require('../helpers') +require('./solution') diff --git a/2023/day-02/input.txt b/2023/day-02/input.txt new file mode 100644 index 0000000..e25a721 --- /dev/null +++ b/2023/day-02/input.txt @@ -0,0 +1,100 @@ +Game 1: 13 red, 18 green; 5 green, 3 red, 5 blue; 5 green, 9 red, 6 blue; 3 blue, 3 green +Game 2: 2 green, 3 blue, 5 red; 9 green, 4 red, 2 blue; 4 green, 3 blue; 2 blue, 3 red; 5 red, 3 blue, 9 green; 9 green, 5 red, 2 blue +Game 3: 12 green, 3 red, 3 blue; 2 blue, 5 green, 2 red; 2 red, 3 blue, 11 green; 2 red, 8 green, 7 blue +Game 4: 1 green, 2 blue; 7 green, 13 red; 2 blue, 5 green, 7 red; 6 green, 2 red +Game 5: 6 blue, 4 green; 8 blue, 7 green; 1 red, 10 blue +Game 6: 4 red, 4 blue, 2 green; 8 green, 1 blue, 8 red; 9 green, 1 red, 3 blue +Game 7: 3 red, 12 green, 4 blue; 1 blue, 3 red, 6 green; 4 blue, 3 red, 15 green; 11 green, 2 blue, 2 red +Game 8: 13 blue, 7 green, 8 red; 5 green, 8 blue, 2 red; 5 red, 6 blue, 7 green; 6 green, 6 red, 3 blue; 7 blue, 8 red, 6 green +Game 9: 4 blue, 1 green, 4 red; 16 red, 1 green, 7 blue; 11 red, 3 green, 7 blue +Game 10: 5 green, 1 red; 5 green, 3 blue; 1 red, 7 green, 3 blue; 1 blue, 6 green; 2 green, 4 blue +Game 11: 10 green, 2 blue, 2 red; 14 green, 1 blue, 3 red; 13 green; 3 green, 2 red; 3 red, 1 blue, 2 green; 1 red, 10 green, 2 blue +Game 12: 9 green, 2 blue; 11 green, 1 blue; 2 red, 1 blue; 1 blue, 2 red, 3 green; 1 blue, 2 red, 3 green +Game 13: 11 blue, 3 red, 8 green; 9 red, 7 blue; 7 blue, 4 red +Game 14: 17 blue, 2 red; 1 green, 13 blue, 1 red; 4 blue, 1 red, 4 green; 2 blue, 5 red, 13 green; 3 blue, 4 green, 6 red; 9 green, 14 blue, 6 red +Game 15: 7 green, 2 blue, 3 red; 4 red, 18 green; 8 green, 1 blue; 3 red, 15 green, 2 blue; 1 red, 15 green; 9 green, 3 red, 1 blue +Game 16: 10 red, 19 blue, 5 green; 12 red, 5 blue; 6 red, 3 green, 14 blue; 8 red, 10 blue, 6 green; 7 green, 10 red, 17 blue +Game 17: 3 green, 3 red, 1 blue; 3 blue, 1 green, 2 red; 4 green, 3 red, 2 blue +Game 18: 1 red, 2 blue; 1 green, 4 blue; 1 blue; 5 blue; 1 green, 3 red, 6 blue +Game 19: 3 blue, 5 red, 8 green; 10 red, 6 blue, 11 green; 5 blue, 7 red, 8 green; 9 blue, 6 green, 5 red; 8 red, 12 green, 8 blue; 1 blue, 5 green, 10 red +Game 20: 16 blue, 2 green; 10 green, 1 red, 4 blue; 13 green, 5 red, 9 blue +Game 21: 1 blue, 1 green, 14 red; 2 blue; 5 green, 1 blue; 2 green, 11 red; 2 red, 4 green; 2 green, 16 red +Game 22: 1 green, 10 red, 4 blue; 1 green, 4 blue, 8 red; 2 blue, 8 red; 4 green, 14 red; 1 blue, 5 red, 2 green +Game 23: 17 green, 3 red, 16 blue; 9 green, 15 red; 3 red, 8 blue, 15 green +Game 24: 1 green, 1 blue; 2 blue, 1 green, 2 red; 3 green, 1 blue, 1 red; 3 blue, 1 red; 2 green, 5 blue +Game 25: 11 red, 2 green; 7 red, 6 green; 10 red, 1 blue, 8 green; 8 green, 4 red; 6 green, 10 red; 2 blue, 7 red +Game 26: 2 green, 2 blue, 8 red; 1 blue, 1 red, 6 green; 9 red, 6 green, 2 blue +Game 27: 5 red, 7 blue, 3 green; 3 blue, 1 red; 1 green, 1 red, 9 blue +Game 28: 17 red, 5 green, 10 blue; 3 red, 14 blue, 1 green; 11 blue, 11 green +Game 29: 16 red, 4 green, 4 blue; 3 green, 5 blue, 11 red; 7 blue, 8 red, 1 green; 1 green, 10 red, 4 blue; 2 green, 4 blue, 8 red +Game 30: 3 green, 6 blue; 18 green, 3 blue; 14 green, 11 blue; 7 blue, 2 red, 17 green; 1 red, 12 green, 7 blue +Game 31: 11 red, 2 green, 3 blue; 10 green, 11 blue, 15 red; 12 green, 17 blue, 5 red; 5 green, 2 red, 12 blue; 13 blue, 13 green, 4 red +Game 32: 4 red, 2 blue, 5 green; 7 blue, 15 red; 11 blue, 4 green, 8 red +Game 33: 18 blue, 3 green, 3 red; 3 green, 6 red; 2 blue, 4 red, 1 green; 3 green, 5 red, 3 blue +Game 34: 5 red, 2 blue, 16 green; 9 red, 10 blue, 3 green; 8 red, 10 green, 13 blue +Game 35: 7 blue, 5 red; 3 red, 1 blue; 4 blue, 7 red, 1 green; 4 red, 4 blue, 1 green; 3 blue, 7 red; 4 red, 1 green, 3 blue +Game 36: 14 blue; 10 blue, 1 green; 10 blue, 4 green; 4 blue, 1 green, 1 red; 1 red, 6 blue, 4 green; 1 green, 1 red, 11 blue +Game 37: 8 red, 13 green, 5 blue; 11 red, 16 green, 8 blue; 2 green, 10 blue, 11 red +Game 38: 2 red, 1 blue, 10 green; 7 red, 6 blue, 14 green; 18 red, 1 blue, 5 green; 5 green, 5 blue, 13 red; 14 red, 5 green; 15 green, 13 red, 2 blue +Game 39: 1 blue, 5 red; 9 red, 9 green; 4 blue, 10 green, 4 red; 3 green, 11 red, 1 blue; 2 green, 11 red, 4 blue +Game 40: 9 blue, 4 green; 12 green, 1 red; 2 red, 15 green, 10 blue +Game 41: 1 blue, 14 red, 12 green; 16 green, 2 blue, 3 red; 6 green, 9 red +Game 42: 4 green, 13 red, 9 blue; 9 green, 9 red, 4 blue; 7 blue, 10 red, 9 green; 4 green, 18 blue, 14 red; 9 blue, 7 green, 2 red +Game 43: 7 red, 6 blue; 4 green; 3 red, 6 green; 7 blue, 6 green, 8 red; 9 green, 7 blue, 7 red; 5 blue, 5 green, 6 red +Game 44: 5 red, 8 blue; 2 red, 5 green; 6 green, 11 blue, 2 red; 1 green, 1 blue, 2 red +Game 45: 3 blue, 7 green, 1 red; 5 red, 1 blue; 2 blue, 3 red; 8 green, 5 red +Game 46: 4 red, 4 blue, 17 green; 1 blue, 5 green, 1 red; 1 red, 1 blue, 7 green; 18 green, 7 blue +Game 47: 14 red, 3 green, 2 blue; 4 green, 4 red, 2 blue; 13 red, 1 blue +Game 48: 5 red, 12 blue, 2 green; 3 blue, 1 red, 2 green; 10 blue, 7 red +Game 49: 6 blue, 11 red; 11 red, 17 blue, 11 green; 16 blue, 12 green, 6 red +Game 50: 12 blue, 3 green, 1 red; 3 green, 10 blue, 3 red; 11 blue, 3 red +Game 51: 12 green, 1 blue, 8 red; 6 blue, 1 green, 9 red; 17 red, 5 blue; 7 blue, 9 green, 9 red; 13 green, 10 red, 2 blue +Game 52: 5 blue, 1 green; 1 red, 1 green, 3 blue; 8 blue, 1 green; 1 green, 7 blue; 3 blue; 1 red, 6 blue +Game 53: 11 green, 5 red; 16 green, 6 blue; 4 red, 19 green, 4 blue +Game 54: 6 green, 4 blue, 8 red; 7 red, 6 green, 5 blue; 5 blue, 4 red; 5 blue, 14 red +Game 55: 11 blue, 1 green; 2 red, 5 blue, 1 green; 10 blue, 1 green; 11 blue; 2 green, 2 red, 5 blue +Game 56: 1 red, 9 blue, 1 green; 2 red, 8 blue; 1 green, 9 blue, 10 red; 5 blue, 1 green; 15 blue, 1 red; 12 blue, 4 red +Game 57: 1 green, 17 blue; 10 blue, 2 green; 2 red, 16 blue; 6 green, 15 blue; 5 green; 2 red, 1 green +Game 58: 2 blue, 4 green, 2 red; 5 blue; 5 red, 3 green, 2 blue; 5 red, 2 green, 5 blue; 7 green, 3 red, 4 blue; 4 red +Game 59: 8 blue, 2 red, 2 green; 15 blue, 1 green, 4 red; 9 blue, 1 red; 3 green, 5 red, 5 blue +Game 60: 3 red, 2 blue, 6 green; 1 red, 5 green; 2 blue, 10 green; 6 green, 2 red +Game 61: 6 green, 4 blue; 1 red, 4 blue, 15 green; 1 blue, 16 green, 3 red; 6 red, 12 green, 2 blue; 3 red, 14 green, 1 blue; 3 red, 2 blue, 9 green +Game 62: 1 green, 2 red; 4 red; 1 green, 4 red, 1 blue; 1 red, 1 blue, 1 green +Game 63: 8 green, 4 red, 4 blue; 5 red, 4 blue, 8 green; 3 green, 1 blue +Game 64: 5 blue, 2 green, 5 red; 3 green, 2 blue, 1 red; 6 blue, 2 red, 1 green; 2 green, 2 blue, 3 red; 3 blue, 1 red +Game 65: 2 red, 7 green, 5 blue; 8 blue, 3 green, 4 red; 1 red, 6 green, 1 blue +Game 66: 1 green, 6 red; 5 red, 1 green, 1 blue; 4 red, 1 blue, 1 green; 1 blue, 2 red, 1 green; 1 blue, 5 red; 1 blue, 8 red +Game 67: 6 red, 8 blue, 8 green; 5 green, 2 red, 10 blue; 4 red, 1 green; 7 blue, 2 green +Game 68: 7 green, 9 red, 15 blue; 4 green, 6 red, 3 blue; 1 blue, 5 green, 4 red; 9 green, 14 red, 6 blue; 8 blue, 15 red, 4 green; 7 green, 14 blue, 6 red +Game 69: 4 green; 2 blue; 4 green, 8 blue, 11 red; 3 green, 9 red, 4 blue; 1 red, 2 blue; 2 green, 5 blue, 11 red +Game 70: 6 blue, 16 green, 4 red; 6 green, 13 red, 2 blue; 7 green, 1 red, 2 blue; 8 green, 4 blue, 1 red; 10 red, 11 green +Game 71: 6 blue, 7 red; 10 blue, 2 green, 4 red; 12 red, 10 blue, 1 green +Game 72: 13 red, 13 blue; 6 red, 10 blue, 7 green; 3 blue, 5 green, 4 red; 8 green, 9 blue +Game 73: 1 red, 1 green, 8 blue; 1 green, 8 blue; 2 green, 6 blue; 2 blue; 1 red, 12 blue; 12 blue, 3 green +Game 74: 2 blue, 1 green, 1 red; 3 blue, 1 red, 1 green; 3 blue, 2 red; 3 blue, 1 red; 1 green +Game 75: 10 red, 1 green, 4 blue; 12 red, 11 blue, 9 green; 18 green, 14 red, 5 blue +Game 76: 4 blue, 3 green, 11 red; 4 blue, 1 green, 12 red; 11 blue, 2 green, 4 red; 2 blue, 2 green, 11 red; 12 red, 1 blue; 4 red, 2 green, 15 blue +Game 77: 2 red, 10 blue, 6 green; 6 blue, 2 red, 8 green; 1 red, 9 green, 7 blue +Game 78: 3 green, 10 red; 2 blue, 4 red, 3 green; 8 red, 3 blue, 4 green; 1 blue, 7 red +Game 79: 4 green, 2 red; 2 red, 14 green; 1 blue, 5 green, 8 red; 4 red, 20 green; 3 green, 1 blue, 8 red; 4 green, 1 blue +Game 80: 2 green; 3 green, 13 red, 10 blue; 6 blue, 10 red, 1 green; 10 green, 12 red, 3 blue; 10 blue, 17 red, 5 green; 8 red, 2 blue, 6 green +Game 81: 4 green, 2 blue, 4 red; 16 red, 1 blue, 20 green; 7 blue, 10 red, 9 green; 7 blue, 2 green, 14 red +Game 82: 4 blue, 8 green, 5 red; 14 red, 8 blue, 1 green; 11 red, 13 green +Game 83: 2 blue, 2 green, 10 red; 10 green, 4 red, 3 blue; 11 green, 14 red, 4 blue; 2 blue, 11 red; 3 blue, 1 green, 4 red +Game 84: 12 blue, 9 green, 10 red; 1 red, 6 green, 4 blue; 7 red, 3 green, 16 blue; 3 green, 3 blue +Game 85: 2 red, 4 blue; 4 blue, 1 green, 6 red; 9 blue, 1 red; 1 green, 4 blue, 10 red; 5 green, 7 red, 17 blue +Game 86: 2 red, 3 blue, 1 green; 2 blue, 2 red, 2 green; 10 blue, 2 green; 5 green, 4 red, 6 blue +Game 87: 1 red, 7 blue, 9 green; 3 green, 2 blue; 1 red, 4 blue, 10 green; 10 green, 7 blue, 1 red; 6 blue, 9 green; 9 blue, 7 green, 1 red +Game 88: 1 blue, 14 red, 9 green; 4 green, 9 red; 8 green, 1 blue, 10 red +Game 89: 13 red, 1 green; 2 blue, 10 red; 1 green, 3 blue, 13 red; 1 green, 14 red, 3 blue; 2 green, 6 red; 1 green, 12 red +Game 90: 1 red, 2 blue, 9 green; 1 blue, 3 red, 2 green; 10 green, 9 red; 1 red, 9 green, 4 blue; 3 blue, 13 green, 13 red +Game 91: 2 red, 8 green, 8 blue; 3 green, 2 red, 6 blue; 5 green, 4 red +Game 92: 8 green, 12 blue, 4 red; 7 red, 4 green; 4 blue, 7 green, 7 red; 7 blue, 5 green +Game 93: 1 green, 1 red, 2 blue; 3 green, 1 red, 3 blue; 1 red, 8 blue; 1 green, 13 blue; 1 red, 4 blue, 4 green +Game 94: 2 blue, 7 red, 17 green; 2 green, 1 blue, 5 red; 3 blue, 7 green, 1 red; 6 red, 1 blue, 1 green; 1 green, 1 blue, 1 red +Game 95: 4 blue, 3 green, 4 red; 17 red, 2 blue; 6 blue, 16 green, 15 red; 7 blue, 17 green; 1 red, 3 green, 3 blue; 7 red, 14 green, 4 blue +Game 96: 6 red, 3 blue; 7 green, 5 blue, 10 red; 9 green, 1 blue; 6 blue, 1 red, 12 green; 3 blue, 10 green +Game 97: 3 green, 1 red, 13 blue; 1 red, 8 green, 2 blue; 1 green, 2 blue, 2 red; 1 red, 4 green, 9 blue +Game 98: 1 green, 8 red, 7 blue; 8 blue, 8 red, 3 green; 1 blue, 2 red; 4 red, 7 blue; 3 green, 3 blue, 3 red +Game 99: 9 blue, 14 red; 3 blue, 10 red, 5 green; 3 blue, 3 green, 6 red +Game 100: 12 blue, 2 green; 2 green, 4 red, 13 blue; 9 blue, 1 red, 2 green; 2 green, 3 red, 1 blue \ No newline at end of file diff --git a/2023/day-02/solution.js b/2023/day-02/solution.js new file mode 100644 index 0000000..01a6c04 --- /dev/null +++ b/2023/day-02/solution.js @@ -0,0 +1,44 @@ +const fs = require('fs') +const path = require('path') +const filePath = path.join(__dirname, 'input.txt') +const { linesToArray } = require('../../2018/inputParser') +const { parseGame, checksumGameSet, power } = require('./game') + +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 + return JSON.parse(JSON.stringify(initData)) + } + + const part1 = () => { + const data = resetInput() + .map(parseGame) + const limit = [12, 13, 14] // 12 red, 13 green, 14 blue + .map((num) => num.toString(16).padStart(2, '0')) + .join('') + console.debug(`limit is ${limit}`) + + return checksumGameSet(data, limit) + } + + const part2 = () => { + const data = resetInput() + .map(parseGame) + + return data.reduce((acc, game) => { + return acc + power(game) + }, 0) + } + const answers = [] + answers.push(part1()) + answers.push(part2()) + + answers.forEach((ans, idx) => { + console.info(`-- Part ${idx + 1} --`) + console.info(`Answer: ${ans}`) + }) +}) diff --git a/README.md b/README.md index 8c09184..ea926d8 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ ## Status ### 2022 -![](https://img.shields.io/badge/day%20📅-5-blue) -![](https://img.shields.io/badge/stars%20⭐-1-yellow) -![](https://img.shields.io/badge/days%20completed-0-red) +![](https://img.shields.io/badge/day%20📅-25-blue) +![](https://img.shields.io/badge/stars%20⭐-4-yellow) +![](https://img.shields.io/badge/days%20completed-2-red) ## Run the currently configured default day `npm start` diff --git a/index.js b/index.js index a1611a7..557add4 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -require('./2023/day-01/solution') +require('./2023/day-02/solution')