├── 2015 ├── css │ ├── hacker.css │ └── styles.css ├── index.html └── js │ ├── day1.js │ ├── day10.js │ ├── day11.js │ ├── day12.js │ ├── day13.js │ ├── day14.js │ ├── day15.js │ ├── day16.js │ ├── day17.js │ ├── day18.js │ ├── day19.js │ ├── day2.js │ ├── day20.js │ ├── day21.js │ ├── day23.js │ ├── day24.js │ ├── day25.js │ ├── day3.js │ ├── day4.js │ ├── day5.js │ ├── day6.js │ ├── day7.js │ ├── day8.js │ └── day9.js ├── 2016 ├── index.html └── js │ ├── day1.js │ ├── day2.js │ ├── day3.js │ ├── day4.js │ ├── day5.js │ ├── day6.js │ ├── day7.js │ └── day8.js ├── 2017 ├── index.html └── js │ ├── day1.js │ ├── day10.js │ ├── day11.js │ ├── day12.js │ ├── day13.js │ ├── day15.js │ ├── day16.js │ ├── day17.js │ ├── day2.js │ ├── day3.js │ ├── day4.js │ ├── day5.js │ ├── day6.js │ ├── day8.js │ └── day9.js ├── 2018 ├── index.html └── js │ ├── day1.js │ ├── day10.js │ ├── day11.js │ ├── day12.js │ ├── day2.js │ ├── day3.js │ ├── day4.js │ ├── day5.js │ ├── day6.js │ ├── day7.js │ ├── day8.js │ └── day9.js ├── 2019 ├── index.js ├── intcode.js ├── js │ ├── day1.js │ ├── day11.js │ ├── day13.js │ ├── day2.js │ ├── day4.js │ ├── day5.js │ ├── day6.js │ ├── day7.js │ ├── day8.js │ └── day9.js ├── package.json └── test.js ├── 2020 ├── index.js ├── js │ ├── day1.js │ ├── day10.js │ ├── day11.js │ ├── day12.js │ ├── day13.js │ ├── day14.js │ ├── day15.js │ ├── day16.js │ ├── day17.js │ ├── day18.js │ ├── day19.js │ ├── day2.js │ ├── day21.js │ ├── day22.js │ ├── day23.js │ ├── day24.js │ ├── day25.js │ ├── day3.js │ ├── day4.js │ ├── day5.js │ ├── day6.js │ ├── day7.js │ ├── day8.js │ └── day9.js ├── package.json └── test.js ├── 2021 ├── .vscode │ ├── launch.json │ └── tasks.json ├── 2021.sln ├── Answers │ ├── 2021.csproj │ ├── AnswerAttribute.cs │ ├── IAnswer.cs │ ├── Program.cs │ ├── Solutions │ │ ├── Day1.cs │ │ ├── Day10.cs │ │ ├── Day11.cs │ │ ├── Day12.cs │ │ ├── Day13.cs │ │ ├── Day14.cs │ │ ├── Day15.cs │ │ ├── Day16.cs │ │ ├── Day17.cs │ │ ├── Day18.cs │ │ ├── Day19.cs │ │ ├── Day2.cs │ │ ├── Day20.cs │ │ ├── Day21.cs │ │ ├── Day22.cs │ │ ├── Day23.cs │ │ ├── Day24.cs │ │ ├── Day25.cs │ │ ├── Day3.cs │ │ ├── Day4.cs │ │ ├── Day5.cs │ │ ├── Day6.cs │ │ ├── Day7.cs │ │ ├── Day8.cs │ │ └── Day9.cs │ └── Solver.cs ├── DataExamples │ ├── answers.txt │ ├── day1.txt │ ├── day10.txt │ ├── day11.txt │ ├── day12.txt │ ├── day13.txt │ ├── day14.txt │ ├── day15.txt │ ├── day16.txt │ ├── day17.txt │ ├── day18.txt │ ├── day19.txt │ ├── day2.txt │ ├── day20.txt │ ├── day21.txt │ ├── day22.txt │ ├── day23.txt │ ├── day24.txt │ ├── day25.txt │ ├── day3.txt │ ├── day4.txt │ ├── day5.txt │ ├── day6.txt │ ├── day7.txt │ ├── day8.txt │ └── day9.txt ├── Tests │ ├── Tests.csproj │ └── UnitTest1.cs └── prep.ps1 ├── 2022 ├── .vscode │ ├── launch.json │ └── tasks.json ├── AdventOfCode.sln ├── Answers │ ├── AdventOfCode.csproj │ ├── AnswerAttribute.cs │ ├── BenchmarkSolver.cs │ ├── IAnswer.cs │ ├── Program.cs │ ├── Solutions │ │ ├── Day0.cs │ │ ├── Day1.cs │ │ ├── Day10.cs │ │ ├── Day11.cs │ │ ├── Day12.cs │ │ ├── Day13.cs │ │ ├── Day14.cs │ │ ├── Day15.cs │ │ ├── Day16.cs │ │ ├── Day17.cs │ │ ├── Day18.cs │ │ ├── Day19.cs │ │ ├── Day2.cs │ │ ├── Day20.cs │ │ ├── Day21.cs │ │ ├── Day22.cs │ │ ├── Day23.cs │ │ ├── Day24.cs │ │ ├── Day25.cs │ │ ├── Day3.cs │ │ ├── Day4.cs │ │ ├── Day5.cs │ │ ├── Day6.cs │ │ ├── Day7.cs │ │ ├── Day8.cs │ │ └── Day9.cs │ └── Solver.cs ├── DataExamples │ ├── answers.txt │ ├── day1.txt │ ├── day10.txt │ ├── day11.txt │ ├── day12.txt │ ├── day13.txt │ ├── day14.txt │ ├── day15.txt │ ├── day16.txt │ ├── day17.txt │ ├── day18.txt │ ├── day19.txt │ ├── day2.txt │ ├── day20.txt │ ├── day21.txt │ ├── day22.txt │ ├── day23.txt │ ├── day24.txt │ ├── day25.txt │ ├── day3.txt │ ├── day4.txt │ ├── day5.txt │ ├── day6.txt │ ├── day7.txt │ ├── day8.txt │ └── day9.txt ├── SolverGenerator │ ├── Properties │ │ └── launchSettings.json │ ├── SolverGenerator.cs │ └── SolverGenerator.csproj ├── Tests │ ├── SolutionTests.cs │ └── Tests.csproj └── prep.ps1 ├── 2023 ├── AdventOfCode.sln ├── Answers │ ├── AdventOfCode.csproj │ ├── AnswerAttribute.cs │ ├── BenchmarkSolver.cs │ ├── IAnswer.cs │ ├── Program.cs │ ├── Solution.cs │ ├── Solutions │ │ ├── Day0.cs │ │ ├── Day1.cs │ │ ├── Day10.cs │ │ ├── Day11.cs │ │ ├── Day12.cs │ │ ├── Day13.cs │ │ ├── Day14.cs │ │ ├── Day15.cs │ │ ├── Day16.cs │ │ ├── Day17.cs │ │ ├── Day18.cs │ │ ├── Day19.cs │ │ ├── Day2.cs │ │ ├── Day20.cs │ │ ├── Day21.cs │ │ ├── Day22.cs │ │ ├── Day23.cs │ │ ├── Day24.cs │ │ ├── Day25.cs │ │ ├── Day3.cs │ │ ├── Day4.cs │ │ ├── Day5.cs │ │ ├── Day6.cs │ │ ├── Day7.cs │ │ ├── Day8.cs │ │ └── Day9.cs │ ├── Solver.cs │ └── Types │ │ └── ReadOnlyGrid.cs ├── DataExamples │ ├── answers.txt │ ├── day1.txt │ ├── day10.txt │ ├── day11.txt │ ├── day12.txt │ ├── day13.txt │ ├── day14.txt │ ├── day15.txt │ ├── day16.txt │ ├── day17.txt │ ├── day18.txt │ ├── day19.txt │ ├── day2.txt │ ├── day20.txt │ ├── day21.txt │ ├── day22.txt │ ├── day23.txt │ ├── day24.txt │ ├── day25.txt │ ├── day3.txt │ ├── day4.txt │ ├── day5.txt │ ├── day6.txt │ ├── day7.txt │ ├── day8.txt │ └── day9.txt ├── SolverGenerator │ ├── Properties │ │ └── launchSettings.json │ ├── SolverGenerator.cs │ └── SolverGenerator.csproj └── prep.ps1 ├── 2024 ├── AdventOfCode.sln ├── Answers │ ├── AdventOfCode.csproj │ ├── AnswerAttribute.cs │ ├── BenchmarkSolver.cs │ ├── IAnswer.cs │ ├── Program.cs │ ├── Solution.cs │ ├── Solutions │ │ ├── Day0.cs │ │ ├── Day1.cs │ │ ├── Day10.cs │ │ ├── Day11.cs │ │ ├── Day12.cs │ │ ├── Day13.cs │ │ ├── Day14.cs │ │ ├── Day15.cs │ │ ├── Day16.cs │ │ ├── Day17.cs │ │ ├── Day18.cs │ │ ├── Day19.cs │ │ ├── Day2.cs │ │ ├── Day20.cs │ │ ├── Day21.cs │ │ ├── Day22.cs │ │ ├── Day23.cs │ │ ├── Day24.cs │ │ ├── Day25.cs │ │ ├── Day3.cs │ │ ├── Day4.cs │ │ ├── Day5.cs │ │ ├── Day6.cs │ │ ├── Day7.cs │ │ ├── Day8.cs │ │ └── Day9.cs │ ├── Solver.cs │ └── Types │ │ └── ReadOnlyGrid.cs ├── DataExamples │ ├── answers.txt │ ├── day1.txt │ ├── day10.txt │ ├── day11.txt │ ├── day12.txt │ ├── day13.txt │ ├── day14.txt │ ├── day15.txt │ ├── day16.txt │ ├── day17.txt │ ├── day18.txt │ ├── day19.txt │ ├── day2.txt │ ├── day20.txt │ ├── day21.txt │ ├── day22.txt │ ├── day23.txt │ ├── day24.txt │ ├── day25.txt │ ├── day3.txt │ ├── day4.txt │ ├── day5.txt │ ├── day6.txt │ ├── day7.txt │ ├── day8.txt │ └── day9.txt ├── SolverGenerator │ ├── Properties │ │ └── launchSettings.json │ ├── SolverGenerator.cs │ └── SolverGenerator.csproj └── prep.ps1 ├── .editorconfig ├── .gitattributes ├── .gitignore └── LICENSE /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = tab 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.ico binary 3 | *.gif binary 4 | *.jpg binary 5 | *.png binary 6 | *.ttf binary 7 | *.woff2 binary 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | node_modules/ 4 | .vs/ 5 | data/ 6 | Data/ 7 | yarn.lock 8 | *.log 9 | BenchmarkDotNet.Artifacts/ 10 | .cookie 11 | -------------------------------------------------------------------------------- /2015/css/styles.css: -------------------------------------------------------------------------------- 1 | .panel > .btn { 2 | margin-top: 3px; 3 | margin-right: 3px; 4 | } 5 | -------------------------------------------------------------------------------- /2015/js/day1.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day1 = function( input ) 2 | { 3 | let floor = 0; 4 | let position = -1; 5 | 6 | // Santa starts on the ground floor (floor 0) and then 7 | // follows the instructions one character at a time. 8 | for( let i = 0; i < input.length; i++ ) 9 | { 10 | // An opening parenthesis, (, means he should go up one floor. 11 | if( input[ i ] === '(' ) 12 | { 13 | floor++; 14 | } 15 | // A closing parenthesis, ), means he should go down one floor. 16 | else 17 | { 18 | floor--; 19 | } 20 | 21 | // Now, given the same instructions, find the position of the first 22 | // character that causes him to enter the basement (floor -1). 23 | // The first character in the instructions has position 1, 24 | // the second character has position 2, and so on. 25 | if( floor === -1 && position < 0 ) 26 | { 27 | // ) causes him to enter the basement at character position 1. 28 | // ()()) causes him to enter the basement at character position 5. 29 | // This is 1-indexed. 30 | position = i + 1; 31 | } 32 | } 33 | 34 | return [ floor, position ]; 35 | }; 36 | -------------------------------------------------------------------------------- /2015/js/day10.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day10 = function( input ) 2 | { 3 | let nextInput = ''; 4 | let fortyLength = 0; 5 | 6 | for( let x = 0; x < 50; x++ ) 7 | { 8 | let currentDigit = input[ 0 ]; 9 | let currentCount = 0; 10 | 11 | for( let i = 0; i < input.length; i++ ) 12 | { 13 | if( currentDigit != input[ i ] ) 14 | { 15 | nextInput += currentCount + '' + currentDigit; 16 | currentDigit = input[ i ]; 17 | currentCount = 1; 18 | } 19 | else 20 | { 21 | currentCount++; 22 | } 23 | } 24 | 25 | nextInput += currentCount + '' + currentDigit; 26 | input = nextInput; 27 | nextInput = ''; 28 | 29 | if( x === 39 ) 30 | { 31 | fortyLength = input.length; 32 | } 33 | } 34 | 35 | return [ fortyLength, input.length ]; 36 | }; 37 | -------------------------------------------------------------------------------- /2015/js/day11.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day11 = function( input ) 2 | { 3 | const increase = /(abc|bcd|cde|def|efg|fgh|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz)/; 4 | const repeat = /(.)\1.*(.)\2/; // BUG: this will match same repeating letters 5 | const illegal = /[iol]/; 6 | const answers = []; 7 | 8 | while( true ) // eslint-disable-line no-constant-condition 9 | { 10 | input = ( ( parseInt( input, 36 ) + 1 ).toString( 36 ) ).replace( /0/g, 'a' ); 11 | 12 | if( !illegal.test( input ) && increase.test( input ) && repeat.test( input ) ) 13 | { 14 | 15 | answers.push( input ); 16 | 17 | if( answers.length === 2 ) 18 | { 19 | return answers; 20 | } 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /2015/js/day12.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day12 = function( input ) 2 | { 3 | input = JSON.parse( input ); 4 | 5 | const SumAllNumbers = function( input, skip ) 6 | { 7 | let result = 0; 8 | 9 | if( typeof input === 'object' ) 10 | { 11 | if( !Array.isArray( input ) ) 12 | { 13 | const keys = Object.keys( input ); 14 | const dirtyResult = []; 15 | 16 | for( let i = 0; i < keys.length; i++ ) 17 | { 18 | const value = input[ keys[ i ] ]; 19 | 20 | // Ignore any object (and all of its children) which has any property with the value "red". 21 | if( value == skip ) 22 | { 23 | return 0; 24 | } 25 | 26 | dirtyResult.push( value ); 27 | } 28 | 29 | input = dirtyResult; 30 | } 31 | 32 | result = input.reduce( function( a, b ) 33 | { 34 | return a + SumAllNumbers( b, skip ); 35 | }, 0 ); 36 | } 37 | else if( typeof input === 'number' ) 38 | { 39 | result = input; 40 | } 41 | 42 | return result; 43 | }; 44 | 45 | const answers = 46 | [ 47 | SumAllNumbers( input, 'kebab' ), 48 | SumAllNumbers( input, 'red' ) 49 | ]; 50 | 51 | return answers; 52 | }; 53 | -------------------------------------------------------------------------------- /2015/js/day14.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day14 = function( input ) 2 | { 3 | let seconds = 2503; 4 | 5 | input = input.split( '\n' ).map( function( a ) 6 | { 7 | const match = a.match( /^(.+) can fly (\d+) km\/s for (\d+) seconds, but then must rest for (\d+) seconds/ ); 8 | 9 | return { 10 | speed: +match[ 2 ], 11 | time: +match[ 3 ], 12 | mustRest: +match[ 4 ], 13 | travellingFor: 0, 14 | distance: 0, 15 | resting: 0, 16 | points: 0 17 | }; 18 | } ); 19 | 20 | let farthestDeer = 0; 21 | let mostPoints = 0; 22 | 23 | while( seconds-- > 0 ) 24 | { 25 | let i, deer, leading = 0; 26 | 27 | for( i = 0; i < input.length; i++ ) 28 | { 29 | deer = input[ i ]; 30 | 31 | if( deer.resting ) 32 | { 33 | deer.resting--; 34 | } 35 | else 36 | { 37 | deer.distance += deer.speed; 38 | 39 | if( ++deer.travellingFor === deer.time ) 40 | { 41 | deer.resting = deer.mustRest; 42 | deer.travellingFor = 0; 43 | } 44 | } 45 | 46 | if( leading < deer.distance ) 47 | { 48 | leading = deer.distance; 49 | } 50 | } 51 | 52 | for( i = 0; i < input.length; i++ ) 53 | { 54 | deer = input[ i ]; 55 | 56 | if( deer.distance === leading ) 57 | { 58 | deer.points++; 59 | } 60 | 61 | if( !seconds ) 62 | { 63 | if( farthestDeer < deer.distance ) 64 | { 65 | farthestDeer = deer.distance; 66 | } 67 | 68 | if( mostPoints < deer.points ) 69 | { 70 | mostPoints = deer.points; 71 | } 72 | } 73 | } 74 | } 75 | 76 | return [ farthestDeer, mostPoints ]; 77 | }; 78 | -------------------------------------------------------------------------------- /2015/js/day15.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day15 = function( input ) 2 | { 3 | input = input.split( '\n' ).map( function( a ) 4 | { 5 | const b = a.match( /.+: .+ (-?\d+), .+ (-?\d+), .+ (-?\d+), .+ (-?\d+), .+ (-?\d+)/ ); 6 | 7 | return [ +b[ 1 ], +b[ 2 ], +b[ 3 ], +b[ 4 ], +b[ 5 ] ]; 8 | } ); 9 | 10 | let totalScore = 0; 11 | let totalScore500 = 0; 12 | 13 | for( let a = 0; a <= 100; a++ ) 14 | for( let b = 0; b <= 100 - a; b++ ) 15 | for( let c = 0; c <= 100 - a - b; c++ ) 16 | { 17 | const d = 100 - a - b - c; 18 | 19 | const cap = input[ 0 ][ 0 ] * a + input[ 1 ][ 0 ] * b + input[ 2 ][ 0 ] * c + input[ 3 ][ 0 ] * d; 20 | const dur = input[ 0 ][ 1 ] * a + input[ 1 ][ 1 ] * b + input[ 2 ][ 1 ] * c + input[ 3 ][ 1 ] * d; 21 | const fla = input[ 0 ][ 2 ] * a + input[ 1 ][ 2 ] * b + input[ 2 ][ 2 ] * c + input[ 3 ][ 2 ] * d; 22 | const tex = input[ 0 ][ 3 ] * a + input[ 1 ][ 3 ] * b + input[ 2 ][ 3 ] * c + input[ 3 ][ 3 ] * d; 23 | const cal = input[ 0 ][ 4 ] * a + input[ 1 ][ 4 ] * b + input[ 2 ][ 4 ] * c + input[ 3 ][ 4 ] * d; 24 | 25 | if( cap <= 0 || dur <= 0 || fla <= 0 || tex <= 0 ) 26 | { 27 | continue; 28 | } 29 | 30 | const score = cap * dur * fla * tex; 31 | 32 | if( totalScore < score ) 33 | { 34 | totalScore = score; 35 | } 36 | 37 | if( totalScore500 < score && cal === 500 ) 38 | { 39 | totalScore500 = score; 40 | } 41 | } 42 | 43 | return [ totalScore, totalScore500 ]; 44 | }; 45 | -------------------------------------------------------------------------------- /2015/js/day16.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day16 = function( input ) 2 | { 3 | const thingsYouRemember = 4 | { 5 | children : '3', 6 | cats : '7', 7 | samoyeds : '2', 8 | pomeranians: '3', 9 | akitas : '0', 10 | vizslas : '0', 11 | goldfish : '5', 12 | trees : '3', 13 | cars : '2', 14 | perfumes : '1' 15 | }; 16 | 17 | input = input.replace( /[,:]/g, '' ).split( '\n' ).map( function( aunt ) 18 | { 19 | return aunt.split( ' ' ); 20 | } ); 21 | 22 | const dayOne = input.filter( function( aunt ) 23 | { 24 | return ( 25 | thingsYouRemember[ aunt[ 2 ] ] == aunt[ 3 ] && 26 | thingsYouRemember[ aunt[ 4 ] ] == aunt[ 5 ] && 27 | thingsYouRemember[ aunt[ 6 ] ] == aunt[ 7 ] ); 28 | } ); 29 | 30 | const filterPartTwo = function( what, count ) 31 | { 32 | if( what === 'cats' || what === 'trees' ) 33 | { 34 | return thingsYouRemember[ what ] < count; 35 | } 36 | 37 | if( what === 'pomeranians' || what === 'goldfish' ) 38 | { 39 | return thingsYouRemember[ what ] > count; 40 | } 41 | 42 | return thingsYouRemember[ what ] == count; 43 | }; 44 | 45 | const dayTwo = input.filter( function( aunt ) 46 | { 47 | return ( 48 | filterPartTwo( aunt[ 2 ], aunt[ 3 ] ) && 49 | filterPartTwo( aunt[ 4 ], aunt[ 5 ] ) && 50 | filterPartTwo( aunt[ 6 ], aunt[ 7 ] ) ); 51 | } ); 52 | 53 | return [ dayOne[ 0 ][ 1 ], dayTwo[ 0 ][ 1 ] ]; 54 | }; 55 | -------------------------------------------------------------------------------- /2015/js/day19.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day19 = function( input ) 2 | { 3 | input = input.split( '' ).reverse().join( '' ).split( '\n' ); 4 | 5 | let molecule = input.shift(); 6 | input.shift(); // empty line 7 | 8 | input = input.map( function( a ) 9 | { 10 | return a.split( ' >= ' ); 11 | } ); 12 | 13 | const uniqueNewMolecules = {}; 14 | let i, y; 15 | 16 | for( i = 0; i < molecule.length; i++ ) 17 | { 18 | for( y = 0; y < input.length; y++ ) 19 | { 20 | if( molecule.substr( i, input[ y ][ 1 ].length ) === input[ y ][ 1 ] ) 21 | { 22 | uniqueNewMolecules[ molecule.slice( 0, i ) + input[ y ][ 0 ] + molecule.slice( i + input[ y ][ 1 ].length ) ] = true; 23 | } 24 | } 25 | } 26 | 27 | let steps = 0; 28 | const lookup = {}; 29 | let replaced = false; 30 | 31 | input = input.map( function( a ) 32 | { 33 | lookup[ a[ 0 ] ] = a[ 1 ]; 34 | 35 | return a[ 0 ]; 36 | } ); 37 | 38 | const regexp = new RegExp( '(' + input.join( '|' ) + ')', 'g' ); 39 | const replaceCallback = function( matched ) 40 | { 41 | replaced = true; 42 | 43 | steps++; 44 | 45 | return lookup[ matched ]; 46 | }; 47 | 48 | do 49 | { 50 | replaced = false; 51 | molecule = molecule.replace( regexp, replaceCallback ); 52 | } 53 | while( replaced ); 54 | 55 | return [ Object.keys( uniqueNewMolecules ).length, steps ]; 56 | }; 57 | -------------------------------------------------------------------------------- /2015/js/day2.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day2 = function( input ) 2 | { 3 | input = input.split( '\n' ); 4 | 5 | let completeArea = 0; 6 | let completeRibbon = 0; 7 | 8 | for( let i = 0; i < input.length; i++ ) 9 | { 10 | // They have a list of the dimensions (length l, width w, and height h) 11 | // of each present, and only want to order exactly as much as they need. 12 | const present = input[ i ] 13 | .split( 'x' ) 14 | .sort( function( a, b ) 15 | { 16 | return a - b; 17 | } ); 18 | 19 | const sides = 20 | [ 21 | present[ 0 ] * present[ 1 ], // l*w 22 | present[ 1 ] * present[ 2 ], // w*h 23 | present[ 2 ] * present[ 0 ] // h*l 24 | ]; 25 | 26 | // Find the surface area of the box, which is 2*l*w + 2*w*h + 2*h*l. 27 | const area = 28 | 2 * sides[ 0 ] + 29 | 2 * sides[ 1 ] + 30 | 2 * sides[ 2 ]; 31 | 32 | // The elves also need a little extra paper for each present: 33 | // the area of the smallest side. 34 | completeArea += area + sides[ 0 ]; 35 | 36 | // The ribbon required to wrap a present is the shortest distance 37 | // around its sides, or the smallest perimeter of any one face. 38 | // Each present also requires a bow made out of ribbon as well; 39 | // the feet of ribbon required for the perfect bow is equal to 40 | // the cubic feet of volume of the present. 41 | const ribbon = 42 | 2 * present[ 0 ] + 43 | 2 * present[ 1 ]; 44 | 45 | const bow = 46 | present[ 0 ] * 47 | present[ 1 ] * 48 | present[ 2 ]; 49 | 50 | completeRibbon += ribbon + bow; 51 | } 52 | 53 | return [ completeArea, completeRibbon ]; 54 | }; 55 | -------------------------------------------------------------------------------- /2015/js/day20.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day20 = function( input ) 2 | { 3 | input = +input; 4 | 5 | let i, j; 6 | const n = 1E6; // Assume no one got input that produced an answer higher than 1mil 7 | const houses = {}; 8 | const housesPartTwo = {}; 9 | 10 | for( i = 1; i < n; i++ ) 11 | { 12 | for( j = i; j < n; j += i ) 13 | { 14 | houses[ j ] = ( houses[ j ] || 0 ) + i * 10; 15 | 16 | if( houses[ j ] >= input ) 17 | { 18 | break; 19 | } 20 | } 21 | 22 | let lazyElfs = 0; 23 | for( j = i; lazyElfs < 50; j += i ) 24 | { 25 | housesPartTwo[ j ] = ( housesPartTwo[ j ] || 0 ) + i * 11; 26 | 27 | if( housesPartTwo[ j ] >= input ) 28 | { 29 | break; 30 | } 31 | 32 | lazyElfs++; 33 | } 34 | } 35 | 36 | for( i = 1; i < input; i++ ) 37 | { 38 | if( houses[ i ] >= input ) 39 | { 40 | break; 41 | } 42 | } 43 | 44 | for( j = 1; j < input; j++ ) 45 | { 46 | if( housesPartTwo[ j ] >= input ) 47 | { 48 | break; 49 | } 50 | } 51 | 52 | return [ i, j ]; 53 | }; 54 | -------------------------------------------------------------------------------- /2015/js/day25.js: -------------------------------------------------------------------------------- 1 | /* globals bigInt */ 2 | window.AdventOfCode.Day25 = function( input ) 3 | { 4 | input = input.match( /([0-9]+)/g ); 5 | 6 | const row = +input[ 0 ]; 7 | const column = +input[ 1 ]; 8 | 9 | const firstCode = 20151125; 10 | const multiplier = 252533; 11 | const divider = 33554393; 12 | 13 | const exp = ( row + column - 2 ) * ( row + column - 1 ) / 2 + column - 1; 14 | const answer = ( bigInt( multiplier ).modPow( exp, divider ) * firstCode ) % divider; 15 | 16 | return [ answer, 'Merry Christmas!' ]; 17 | }; 18 | -------------------------------------------------------------------------------- /2015/js/day3.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day3 = function( input ) 2 | { 3 | const GetUniqueHouses = function( numberOfSantas ) 4 | { 5 | let uniqueHousesCount = 1; 6 | const uniqueHouses = 7 | { 8 | '0x0': 1 9 | }; 10 | 11 | for( let santa = 0; santa < numberOfSantas; santa++ ) 12 | { 13 | // Santa is delivering presents to an infinite two-dimensional grid of houses. 14 | let x = 0, y = 0; 15 | 16 | // Then an elf at the North Pole calls him via radio and tells him where to move next. 17 | for( let i = santa; i < input.length; i += numberOfSantas ) 18 | { 19 | switch( input[ i ] ) 20 | { 21 | case '^': x++; break; 22 | case 'v': x--; break; 23 | case '>': y++; break; 24 | case '<': y--; break; 25 | } 26 | 27 | const coord = x + 'x' + y; 28 | 29 | if( !uniqueHouses[ coord ] ) 30 | { 31 | uniqueHousesCount++; 32 | 33 | uniqueHouses[ coord ] = 1; 34 | } 35 | } 36 | } 37 | 38 | return uniqueHousesCount; 39 | }; 40 | 41 | return [ GetUniqueHouses( 1 ), GetUniqueHouses( 2 ) ]; 42 | }; 43 | -------------------------------------------------------------------------------- /2015/js/day5.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day5 = function( input ) 2 | { 3 | input = input.split( '\n' ); 4 | 5 | // It contains at least three vowels (aeiou only), 6 | // like aei, xazegov, or aeiouaeiouaeiou. 7 | const regexVowels = /[aeiou]/g; 8 | 9 | // It contains at least one letter that appears twice in a row, 10 | // like xx, abcdde (dd), or aabbccdd (aa, bb, cc, or dd). 11 | const regexDoubleLetter = /(.)\1+/; 12 | 13 | // It does not contain the strings ab, cd, pq, or xy, 14 | // even if they are part of one of the other requirements. 15 | const regexNaughtyParts = /(ab|cd|pq|xy)/; 16 | 17 | // It contains a pair of any two letters that appears at least 18 | // twice in the string without overlapping, like xyxy (xy) or 19 | // aabcdefgaa (aa), but not like aaa (aa, but it overlaps). 20 | const regexRepeat = /(..).*\1/; 21 | 22 | // It contains at least one letter which repeats with exactly one 23 | // letter between them, like xyx, abcdefeghi (efe), or even aaa. 24 | const regexSpaced = /(.).\1/; 25 | 26 | const PartOneFilter = function( word ) 27 | { 28 | const match = word.match( regexVowels ); 29 | 30 | return ( match !== null && match.length >= 3 31 | && regexDoubleLetter.test( word ) 32 | && !regexNaughtyParts.test( word ) ); 33 | }; 34 | 35 | const PartTwoFilter = function( word ) 36 | { 37 | return regexRepeat.test( word ) && regexSpaced.test( word ); 38 | }; 39 | 40 | return [ input.filter( PartOneFilter ).length, input.filter( PartTwoFilter ).length ]; 41 | }; 42 | -------------------------------------------------------------------------------- /2015/js/day8.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day8 = function( input ) 2 | { 3 | input = input.split( '\n' ); 4 | 5 | let totalLength = 0; 6 | let cleanLength = 0; 7 | let encodedLength = 0; 8 | 9 | for( let i = 0; i < input.length; i++ ) 10 | { 11 | const str = input[ i ]; 12 | let escaping = false; 13 | 14 | totalLength += str.length; 15 | encodedLength += str.length + 4; 16 | 17 | for( let x = 1; x < str.length - 1; x++ ) 18 | { 19 | const char = str[ x ]; 20 | 21 | if( escaping ) 22 | { 23 | escaping = false; 24 | 25 | if( char === 'x' ) 26 | { 27 | x += 2; 28 | } 29 | else 30 | { 31 | encodedLength++; 32 | } 33 | } 34 | else if( char === '\\' ) 35 | { 36 | encodedLength++; 37 | 38 | escaping = true; 39 | 40 | continue; 41 | } 42 | 43 | cleanLength++; 44 | } 45 | } 46 | 47 | return [ totalLength - cleanLength, encodedLength - totalLength ]; 48 | }; 49 | -------------------------------------------------------------------------------- /2015/js/day9.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day9 = function( input ) 2 | { 3 | const permutator = function( inputArr ) 4 | { 5 | const results = []; 6 | 7 | function permute( arr, memo ) 8 | { 9 | let cur; memo = memo || []; 10 | 11 | for( let i = 0; i < arr.length; i++ ) 12 | { 13 | cur = arr.splice( i, 1 ); 14 | if( arr.length === 0 ) 15 | { 16 | results.push( memo.concat( cur ) ); 17 | } 18 | permute( arr.slice(), memo.concat( cur ) ); 19 | arr.splice( i, 0, cur[ 0 ] ); 20 | } 21 | 22 | return results; 23 | } 24 | 25 | return permute( inputArr ); 26 | }; 27 | 28 | input = input.split( '\n' ); 29 | const travelPaths = {}; 30 | const cities = {}; 31 | 32 | for( let i = 0; i < input.length; i++ ) 33 | { 34 | const data = input[ i ].split( ' ' ); 35 | 36 | if( !cities[ data[ 0 ] ] ) 37 | { 38 | cities[ data[ 0 ] ] = true; 39 | travelPaths[ data[ 0 ] ] = {}; 40 | } 41 | 42 | if( !cities[ data[ 2 ] ] ) 43 | { 44 | cities[ data[ 2 ] ] = true; 45 | travelPaths[ data[ 2 ] ] = {}; 46 | } 47 | 48 | travelPaths[ data[ 0 ] ][ data[ 2 ] ] = +data[ 4 ]; 49 | travelPaths[ data[ 2 ] ][ data[ 0 ] ] = +data[ 4 ]; 50 | } 51 | 52 | const permuted = permutator( Object.keys( cities ) ); 53 | let shortestDistance = Number.MAX_VALUE; 54 | let longestDistance = 0; 55 | 56 | for( let i = 0; i < permuted.length; i++ ) 57 | { 58 | let distance = 0; 59 | 60 | for( let x = 1; x < permuted[ i ].length; x++ ) 61 | { 62 | distance += travelPaths[ permuted[ i ][ x - 1 ] ][ permuted[ i ][ x ] ]; 63 | } 64 | 65 | if( shortestDistance > distance ) 66 | { 67 | shortestDistance = distance; 68 | } 69 | 70 | if( longestDistance < distance ) 71 | { 72 | longestDistance = distance; 73 | } 74 | } 75 | 76 | return [ shortestDistance, longestDistance ]; 77 | }; 78 | -------------------------------------------------------------------------------- /2016/js/day1.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day1 = function( input ) 2 | { 3 | input = input.split( ', ' ); 4 | 5 | const visited = new Set(); 6 | let visitedTwiceDistance = null; 7 | let direction = 0; 8 | const position = { x: 0, y: 0 }; 9 | 10 | for( let i of input ) 11 | { 12 | const turn = i[ 0 ] === 'L' ? -1 : 1; 13 | const coordinate = direction % 2 === 1 ? 'x' : 'y'; 14 | let travel = +i.substring( 1 ); 15 | 16 | direction = ( direction + turn + 4 ) % 4; 17 | 18 | if( direction > 1 ) 19 | { 20 | travel *= -1; 21 | } 22 | 23 | const start = { x: position.x, y: position.y }; 24 | position[ coordinate ] += travel; 25 | 26 | if( visitedTwiceDistance === null ) 27 | { 28 | const end = position; 29 | let x = start.x; 30 | 31 | xLoop: 32 | do 33 | { 34 | let y = start.y; 35 | 36 | do 37 | { 38 | i = x + "." + y; 39 | 40 | if( visited.has( i ) ) 41 | { 42 | visitedTwiceDistance = Math.abs( x ) + Math.abs( y ); 43 | break xLoop; 44 | } 45 | else 46 | { 47 | visited.add( i ); 48 | } 49 | 50 | if( y !== end.y ) 51 | { 52 | direction > 1 ? y-- : y++; 53 | } 54 | } 55 | while( y !== end.y ); 56 | 57 | if( x !== end.x ) 58 | { 59 | direction > 1 ? x-- : x++; 60 | } 61 | } 62 | while( x !== end.x ); 63 | } 64 | } 65 | 66 | return [ Math.abs( position.x ) + Math.abs( position.y ), visitedTwiceDistance ]; 67 | }; 68 | -------------------------------------------------------------------------------- /2016/js/day2.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day2 = function( input ) 2 | { 3 | input = input.split( '\n' ); 4 | 5 | // Part 1 6 | let keypad = 7 | [ 8 | [ 1, 2, 3 ], 9 | [ 4, 5, 6 ], 10 | [ 7, 8, 9 ], 11 | ]; 12 | 13 | const Clamp = function( i ) 14 | { 15 | return i < 0 ? 0 : i > 2 ? 2 : i; 16 | }; 17 | 18 | let position = { x: 1, y: 1 }; 19 | let part1 = ""; 20 | 21 | for( const line of input ) 22 | { 23 | for( const i of line ) 24 | { 25 | switch( i ) 26 | { 27 | case 'L': position.x--; break; 28 | case 'R': position.x++; break; 29 | case 'U': position.y--; break; 30 | case 'D': position.y++; break; 31 | } 32 | 33 | position.x = Clamp( position.x ); 34 | position.y = Clamp( position.y ); 35 | } 36 | 37 | part1 += keypad[ position.y ][ position.x ]; 38 | } 39 | 40 | // Part 2 41 | keypad = 42 | [ 43 | [ null, null, 1, null, null ], 44 | [ null, 2, 3, 4, null ], 45 | [ 5, 6, 7, 8, 9 ], 46 | [ null, 'A', 'B', 'C', null ], 47 | [ null, null, 'D', null, null ], 48 | ]; 49 | 50 | const IsValidPosition = function() 51 | { 52 | if( !keypad[ position.y ] ) 53 | { 54 | return false; 55 | } 56 | 57 | return !!keypad[ position.y ][ position.x ]; 58 | }; 59 | 60 | position = { x: 0, y: 2 }; 61 | let part2 = ""; 62 | 63 | for( const line of input ) 64 | { 65 | for( const i of line ) 66 | { 67 | const currentPosition = { x: position.x, y: position.y }; 68 | 69 | switch( i ) 70 | { 71 | case 'L': position.x--; break; 72 | case 'R': position.x++; break; 73 | case 'U': position.y--; break; 74 | case 'D': position.y++; break; 75 | } 76 | 77 | if( !IsValidPosition() ) 78 | { 79 | position = currentPosition; 80 | } 81 | } 82 | 83 | part2 += keypad[ position.y ][ position.x ]; 84 | } 85 | 86 | return [ part1, part2 ]; 87 | }; 88 | -------------------------------------------------------------------------------- /2016/js/day3.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day3 = function( input ) 2 | { 3 | const part1 = input.split( '\n' ); 4 | const part2 = input.replace( 5 | /(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/gm, 6 | '$1 $4 $7\n' + 7 | '$2 $5 $8\n' + 8 | '$3 $6 $9' 9 | ).split( '\n' ); 10 | 11 | function IsValidTriangle( a, b, c ) 12 | { 13 | return a + b > c && a + c > b && b + c > a; 14 | } 15 | 16 | function CountValidTriangles( lines ) 17 | { 18 | let triangles = 0; 19 | 20 | for( let line of lines ) 21 | { 22 | line = line.match( /(\d+)\s+(\d+)\s+(\d+)/ ); 23 | 24 | if( IsValidTriangle( +line[ 1 ], +line[ 2 ], +line[ 3 ] ) ) 25 | { 26 | triangles++; 27 | } 28 | } 29 | 30 | return triangles; 31 | } 32 | 33 | return [ CountValidTriangles( part1 ), CountValidTriangles( part2 ) ]; 34 | }; 35 | -------------------------------------------------------------------------------- /2016/js/day4.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day4 = function( input ) 2 | { 3 | input = input.split( '\n' ); 4 | 5 | let validRooms = 0; 6 | let northpoleObjectStorage = -1; 7 | 8 | for( let line of input ) 9 | { 10 | line = line.match( /(.+?)-(\d+)\[([a-z]+)\]/ ); 11 | 12 | const name = line[ 1 ]; 13 | const sector = +line[ 2 ]; 14 | const checksum = line[ 3 ]; 15 | const letters = line[ 1 ].match( /[a-z]/g ); 16 | const countedLetters = new Map(); 17 | 18 | for( const letter of letters ) 19 | { 20 | countedLetters.set( letter, 1 + countedLetters.get( letter ) || 0 ); 21 | } 22 | 23 | let sortedLetters = []; 24 | 25 | for( const letter of countedLetters ) 26 | { 27 | sortedLetters.push( letter ); 28 | } 29 | 30 | sortedLetters = sortedLetters 31 | .sort( ( a, b ) => 32 | { 33 | if( a[ 1 ] === b[ 1 ] ) 34 | { 35 | return a[ 0 ] > b[ 0 ] ? 1 : -1; 36 | } 37 | 38 | return b[ 1 ] - a[ 1 ]; 39 | } ) 40 | .map( letter => letter[ 0 ] ); 41 | 42 | const actualChecksum = sortedLetters.join( '' ).substring( 0, 5 ); 43 | 44 | if( checksum === actualChecksum ) 45 | { 46 | validRooms += sector; 47 | 48 | if( northpoleObjectStorage === -1 ) 49 | { 50 | let decryptedName = ""; 51 | 52 | for( const letter of name ) 53 | { 54 | if( letter === '-' ) 55 | { 56 | decryptedName += ' '; 57 | continue; 58 | } 59 | 60 | decryptedName += String.fromCharCode( ( letter.charCodeAt( 0 ) - 97 + sector ) % 26 + 97 ); 61 | } 62 | 63 | if( decryptedName === 'northpole object storage' ) 64 | { 65 | northpoleObjectStorage = sector; 66 | } 67 | } 68 | } 69 | } 70 | 71 | return [ validRooms, northpoleObjectStorage ]; 72 | }; 73 | -------------------------------------------------------------------------------- /2016/js/day5.js: -------------------------------------------------------------------------------- 1 | /* globals SparkMD5 */ 2 | window.AdventOfCode.Day5 = function( input ) 3 | { 4 | let i = 2307654; 5 | let hash; 6 | let part1password = ''; 7 | const part2password = []; 8 | 9 | do 10 | { 11 | hash = SparkMD5.hash( input + i++ ); 12 | 13 | if( hash[ 0 ] === '0' 14 | && hash[ 1 ] === '0' 15 | && hash[ 2 ] === '0' 16 | && hash[ 3 ] === '0' 17 | && hash[ 4 ] === '0' ) 18 | { 19 | const position = hash[ 5 ]; 20 | 21 | if( part1password.length < 8 ) 22 | { 23 | part1password += position; 24 | } 25 | 26 | if( position >= 0 && position <= 7 && part2password[ position ] === undefined ) 27 | { 28 | part2password[ position ] = hash[ 6 ]; 29 | } 30 | 31 | if( part1password.length === 8 && part2password.filter( () => true ).length === 8 ) 32 | { 33 | break; 34 | } 35 | } 36 | } 37 | while( true ); // eslint-disable-line no-constant-condition 38 | 39 | return [ part1password, part2password.join( '' ) ]; 40 | }; 41 | -------------------------------------------------------------------------------- /2016/js/day6.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day6 = function( input ) 2 | { 3 | input = input.split( '\n' ); 4 | 5 | const countedLetters = []; 6 | 7 | for( const line of input ) 8 | { 9 | for( let i = 0; i < line.length; i++ ) 10 | { 11 | if( !countedLetters[ i ] ) 12 | { 13 | countedLetters[ i ] = new Map(); 14 | } 15 | 16 | countedLetters[ i ].set( line[ i ], 1 + countedLetters[ i ].get( line[ i ] ) || 0 ); 17 | } 18 | } 19 | 20 | let message1 = ""; 21 | let message2 = ""; 22 | 23 | for( const letters of countedLetters ) 24 | { 25 | let commonLetter = ''; 26 | let commonLetterCount = 0; 27 | let notCommonLetter = ''; 28 | let notCommonLetterCount = Infinity; 29 | 30 | for( const letter of letters ) 31 | { 32 | if( commonLetterCount < letter[ 1 ] ) 33 | { 34 | commonLetterCount = letter[ 1 ]; 35 | commonLetter = letter[ 0 ]; 36 | } 37 | 38 | if( notCommonLetterCount > letter[ 1 ] ) 39 | { 40 | notCommonLetterCount = letter[ 1 ]; 41 | notCommonLetter = letter[ 0 ]; 42 | } 43 | } 44 | 45 | message1 += commonLetter; 46 | message2 += notCommonLetter; 47 | } 48 | 49 | return [ message1, message2 ]; 50 | }; 51 | -------------------------------------------------------------------------------- /2016/js/day8.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day8 = function( input ) 2 | { 3 | input = input.split( '\n' ); 4 | 5 | const grid = []; 6 | 7 | for( let x = 0; x < 6; x++ ) 8 | { 9 | grid[ x ] = []; 10 | 11 | for( let y = 0; y < 50; y++ ) 12 | { 13 | grid[ x ][ y ] = false; 14 | } 15 | } 16 | 17 | for( const line of input ) 18 | { 19 | const rect = line.match( /^rect (\d+)x(\d+)$/ ); 20 | 21 | if( rect ) 22 | { 23 | const min = +rect[ 1 ]; 24 | const max = +rect[ 2 ]; 25 | 26 | for( let x = 0; x < max; x++ ) 27 | { 28 | for( let y = 0; y < min; y++ ) 29 | { 30 | grid[ x ][ y ] = true; 31 | } 32 | } 33 | } 34 | else 35 | { 36 | const rotate = line.match( /^rotate (row y|column x)=(\d+) by (\d+)$/ ); 37 | 38 | const what = +rotate[ 2 ]; 39 | const much = +rotate[ 3 ]; 40 | 41 | // JAVASCRIPT PLES 42 | const oldGrid = []; 43 | for( let x = 0; x < grid.length; x++ ) 44 | { 45 | oldGrid[ x ] = grid[ x ].slice(); 46 | } 47 | 48 | if( rotate[ 1 ] === 'row y' ) 49 | { 50 | for( let y = 0; y < 50; y++ ) 51 | { 52 | grid[ what ][ ( y + much ) % 50 ] = oldGrid[ what ][ y ]; 53 | } 54 | } 55 | else 56 | { 57 | for( let x = 0; x < 6; x++ ) 58 | { 59 | grid[ ( x + much ) % 6 ][ what ] = oldGrid[ x ][ what ]; 60 | } 61 | } 62 | } 63 | } 64 | 65 | let part1 = 0; 66 | 67 | for( let x = 0; x < grid.length; x++ ) 68 | { 69 | let line = ''; 70 | 71 | for( let y = 0; y < grid[ x ].length; y++ ) 72 | { 73 | line += grid[ x ][ y ] ? '#' : ' '; 74 | 75 | if( grid[ x ][ y ] ) 76 | { 77 | part1++; 78 | } 79 | } 80 | 81 | console.log( line ); 82 | } 83 | 84 | return [ part1, 'See console' ]; 85 | }; 86 | -------------------------------------------------------------------------------- /2017/js/day1.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day1 = function( input ) 2 | { 3 | input = input.split( '' ); 4 | 5 | let sum = 0; 6 | let sumHalf = 0; 7 | const half = input.length / 2; 8 | 9 | for( let i = 0; i < input.length; i++ ) 10 | { 11 | const current = input[ i ]; 12 | const next = input[ ( i + 1 ) % input.length ]; 13 | const nextHalf = input[ ( i + half ) % input.length ]; 14 | 15 | if( current === next ) 16 | { 17 | sum += +current; 18 | } 19 | 20 | if( current === nextHalf ) 21 | { 22 | sumHalf += +current; 23 | } 24 | } 25 | 26 | return [ sum, sumHalf ]; 27 | }; 28 | -------------------------------------------------------------------------------- /2017/js/day10.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day10 = function( input ) 2 | { 3 | const toHex = ( sequence ) => sequence.map( ( x ) => x.toString( 16 ).padStart( 2, '0' ) ).join( '' ); 4 | 5 | const dense = ( list ) => 6 | { 7 | const denseList = []; 8 | 9 | for( let i = 0; i < 16; i++ ) 10 | { 11 | denseList.push( list.slice( i * 16, 16 + i * 16 ).reduce( ( a, b ) => a ^ b ) ); 12 | } 13 | 14 | return denseList; 15 | }; 16 | 17 | const hash = ( list, lengths, rounds = 1 ) => 18 | { 19 | let position = 0; 20 | let globalSkip = 0; 21 | 22 | for( let round = 0; round < rounds; round++ ) 23 | { 24 | for( let i = 0; i < lengths.length; i++ ) 25 | { 26 | const reversed = []; 27 | 28 | for( let skip = 0; skip < lengths[ i ]; skip++ ) 29 | { 30 | reversed.unshift( list[ ( position + skip ) % list.length ] ); 31 | } 32 | 33 | for( let skip = 0; skip < lengths[ i ]; skip++ ) 34 | { 35 | list[ ( position + skip ) % list.length ] = reversed[ skip ]; 36 | } 37 | 38 | position = ( position + lengths[ i ] + globalSkip++ ) % list.length; 39 | } 40 | } 41 | 42 | return list; 43 | }; 44 | 45 | const lengths = input 46 | .split( ',' ) 47 | .map( ( num ) => parseInt( num, 10 ) ); 48 | let part1 = hash( [ ...Array( 256 ).keys() ], lengths ); 49 | part1 = part1[ 0 ] * part1[ 1 ]; 50 | 51 | const bytes = input 52 | .split( '' ) 53 | .map( ( c ) => c.charCodeAt( 0 ) ) 54 | .concat( [ 17, 31, 73, 47, 23 ] ); 55 | let part2 = hash( [ ...Array( 256 ).keys() ], bytes, 64 ); 56 | part2 = toHex( dense( part2 ) ); 57 | 58 | return [ part1, part2 ]; 59 | }; 60 | -------------------------------------------------------------------------------- /2017/js/day11.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day11 = function( input ) 2 | { 3 | const distances = []; 4 | let x = 0; 5 | let y = 0; 6 | let z = 0; 7 | 8 | input.split( ',' ).forEach( ( direction ) => 9 | { 10 | switch( direction ) 11 | { 12 | case 'n': y++; z--; break; 13 | case 's': y--; z++; break; 14 | case 'se': x++; y--; break; 15 | case 'sw': x--; z++; break; 16 | case 'ne': x++; z--; break; 17 | case 'nw': x--; y++; break; 18 | } 19 | 20 | distances.push( ( Math.abs( x ) + Math.abs( y ) + Math.abs( z ) ) / 2 ); 21 | } ); 22 | 23 | const part1 = distances[ distances.length - 1 ]; 24 | const part2 = Math.max( ...distances ); 25 | 26 | return [ part1, part2 ]; 27 | }; 28 | -------------------------------------------------------------------------------- /2017/js/day12.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day12 = function( input ) 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( ( line ) => line 6 | .split( ' <-> ' )[ 1 ] 7 | .split( ', ' ) 8 | .map( ( id ) => parseInt( id, 10 ) ) 9 | ); 10 | 11 | const visited = new Map(); 12 | 13 | const visit = ( value, id ) => 14 | { 15 | if( visited.has( id ) ) 16 | { 17 | return 0; 18 | } 19 | 20 | visited.set( id, true ); 21 | 22 | return value.reduce( ( total, nextId ) => total + visit( input[ nextId ], nextId ), 1 ); 23 | }; 24 | 25 | input = input.map( visit ); 26 | 27 | const part1 = input[ 0 ]; 28 | const part2 = input.reduce( ( total, x ) => x > 0 ? ++total : total, 0 ); 29 | 30 | return [ part1, part2 ]; 31 | }; 32 | -------------------------------------------------------------------------------- /2017/js/day13.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day13 = function( input ) 2 | { 3 | input = input.split( '\n' ).map( ( line ) => line.split( ': ' ).map( ( num ) => parseInt( num, 10 ) ) ); 4 | 5 | const part1 = input 6 | .filter( ( [ depth, range ] ) => depth % ( ( range - 1 ) * 2 ) === 0 ) 7 | .reduce( ( count, [ depth, range ] ) => count + depth * range, 0 ); 8 | 9 | let part2 = -1; 10 | const isCaught = delay => ( [ depth, range ] ) => ( delay + depth ) % ( 2 * ( range - 1 ) ) === 0; 11 | 12 | while( input.some( isCaught( ++part2 ) ) ); 13 | 14 | return [ part1, part2 ]; 15 | }; 16 | -------------------------------------------------------------------------------- /2017/js/day15.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day15 = function( input ) 2 | { 3 | input = input.match( /(\d+)/g ); 4 | 5 | const A = +input[ 0 ]; 6 | const B = +input[ 1 ]; 7 | 8 | const factorA = 16807; 9 | const factorB = 48271; 10 | const product = 2147483647; 11 | 12 | const generate = ( value, factor, multiplier ) => 13 | { 14 | const newValue = value * factor % product; 15 | 16 | if( newValue % multiplier ) 17 | { 18 | return generate( newValue, factor, multiplier ); 19 | } 20 | 21 | return newValue; 22 | }; 23 | 24 | const count = ( a, b, iterations, multiplierA, multiplierB ) => 25 | { 26 | let count = 0; 27 | 28 | while( iterations-- > 0 ) 29 | { 30 | a = generate( a, factorA, multiplierA ); 31 | b = generate( b, factorB, multiplierB ); 32 | count += ( a & 0xFFFF ) === ( b & 0xFFFF ); 33 | } 34 | 35 | return count; 36 | }; 37 | 38 | const part1 = count( A, B, 40000000, 1, 1 ); 39 | const part2 = count( A, B, 5000000, 4, 8 ); 40 | 41 | return [ part1, part2 ]; 42 | }; 43 | -------------------------------------------------------------------------------- /2017/js/day16.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day16 = function( input ) 2 | { 3 | input = input.split( ',' ); 4 | 5 | const permutations = []; 6 | const dancers = 'abcdefghijklmnop'; 7 | let dancer = dancers.split( '' ); 8 | let newDancer = dancers; 9 | 10 | const functions = 11 | { 12 | x: ( a, b ) => [ dancer[ a ], dancer[ b ] ] = [ dancer[ b ], dancer[ a ] ], 13 | p: ( a, b ) => functions.x( dancer.indexOf( a ), dancer.indexOf( b ) ), 14 | s: ( a ) => dancer = [ ...dancer.slice( -a ), ...dancer.slice( 0, -a ) ], 15 | }; 16 | 17 | do 18 | { 19 | permutations.push( newDancer ); 20 | 21 | input.forEach( d => functions[ d.charAt( 0 ) ]( ...d.substr( 1 ).split( '/' ) ) ); 22 | 23 | newDancer = dancer.join( '' ); 24 | } 25 | while( newDancer !== 'abcdefghijklmnop' ); 26 | 27 | const part1 = permutations[ 1 ]; 28 | const part2 = permutations[ 1000000000 % permutations.length ]; 29 | 30 | return [ part1, part2 ]; 31 | }; 32 | -------------------------------------------------------------------------------- /2017/js/day17.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day17 = function( input ) 2 | { 3 | input = parseInt( input, 10 ); 4 | 5 | const buffer = [ 0 ]; 6 | let step = 0; 7 | 8 | for( let i = 1; i <= 2017; i++ ) 9 | { 10 | step = ( step + input + 1 ) % i; 11 | buffer.splice( step, 0, i ); 12 | } 13 | 14 | const part1 = buffer[ ( step + 1 ) % buffer.length ]; 15 | let part2 = 0; 16 | 17 | for( let i = 1; i <= 50000000; i++ ) 18 | { 19 | step = ( step + input + 1 ) % i; 20 | 21 | if( step == 0 ) 22 | { 23 | part2 = i; 24 | } 25 | } 26 | 27 | return [ part1, part2 ]; 28 | }; 29 | -------------------------------------------------------------------------------- /2017/js/day2.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day2 = function( input ) 2 | { 3 | input = input.split( '\n' ).map( ( line ) => line.split( /\s/ ) ); 4 | 5 | const part1 = input.reduce( ( rowAccumulator, row ) => 6 | { 7 | row.sort( ( a, b ) => a - b ); 8 | 9 | return rowAccumulator + +row[ row.length - 1 ] - +row[ 0 ]; 10 | }, 0 ); 11 | 12 | const part2 = input.reduce( ( rowAccumulator, row ) => 13 | { 14 | const division = 0; 15 | 16 | for( let i = 0; i < row.length; i++ ) 17 | { 18 | for( let x = 0; x < row.length; x++ ) 19 | { 20 | if( i !== x && row[ i ] % row[ x ] === 0 ) 21 | { 22 | console.log( row[ i ], row[ x ], division ); 23 | } 24 | } 25 | } 26 | 27 | return rowAccumulator + division; 28 | }, 0 ); 29 | 30 | return [ part1, part2 ]; 31 | }; 32 | -------------------------------------------------------------------------------- /2017/js/day3.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day3 = function( input ) 2 | { 3 | input = +input; 4 | 5 | // https://www.reddit.com/r/adventofcode/comments/7h7ufl/2017_day_3_solutions/dqoxrb7/ 6 | const root = Math.ceil( Math.sqrt( input ) ); 7 | const sideLength = root % 2 !== 0 ? root : root + 1; 8 | const centerLength = ( sideLength - 1 ) / 2; 9 | const cycle = input - Math.pow( ( sideLength - 2 ), 2 ); 10 | const innerOffset = cycle % ( sideLength - 1 ); 11 | const part1 = centerLength + Math.abs( innerOffset - centerLength ); 12 | 13 | fetch( 'https://cors-anywhere.herokuapp.com/https://oeis.org/A141481/b141481.txt' ) 14 | .then( ( response ) => 15 | { 16 | return response.text(); 17 | } ) 18 | .then( ( response ) => 19 | { 20 | response = response 21 | .split( '\n' ) 22 | .map( ( line ) => line.split( ' ' )[ 1 ] ); 23 | 24 | const part2 = response.find( ( value ) => value > input ); 25 | console.log( part2 ); 26 | } ); 27 | 28 | // Can't be bothered to write code for part 2 29 | return [ part1, 'console' ]; 30 | }; 31 | -------------------------------------------------------------------------------- /2017/js/day4.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day4 = function( input ) 2 | { 3 | input = input.split( '\n' ).map( ( pass ) => pass.split( ' ' ) ); 4 | 5 | const countValid = ( counter, pass ) => 6 | { 7 | if( ( new Set( pass ) ).size === pass.length ) 8 | { 9 | counter++; 10 | } 11 | 12 | return counter; 13 | }; 14 | 15 | const part1 = input.reduce( countValid, 0 ); 16 | 17 | const part2 = input 18 | .map( ( pass ) => pass.map( ( word ) => [ ...word ].sort( ).join( '' ) ) ) 19 | .reduce( countValid, 0 ); 20 | 21 | return [ part1, part2 ]; 22 | }; 23 | -------------------------------------------------------------------------------- /2017/js/day5.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day5 = function( input ) 2 | { 3 | const part2offsets = input.split( '\n' ).map( ( num ) => parseInt( num, 10 ) ); 4 | 5 | const part1offsets = [ ...part2offsets ]; 6 | let offset = 0; 7 | let part1 = 0; 8 | let part2 = 0; 9 | 10 | do 11 | { 12 | part1++; 13 | 14 | const nextOffset = part1offsets[ offset ]; 15 | 16 | part1offsets[ offset ]++; 17 | 18 | offset += nextOffset; 19 | } 20 | while( offset > -1 && offset < part1offsets.length ); 21 | 22 | offset = 0; 23 | 24 | do 25 | { 26 | part2++; 27 | 28 | const nextOffset = part2offsets[ offset ]; 29 | 30 | if( nextOffset >= 3 ) 31 | { 32 | part2offsets[ offset ]--; 33 | } 34 | else 35 | { 36 | part2offsets[ offset ]++; 37 | } 38 | 39 | offset += nextOffset; 40 | } 41 | while( offset > -1 && offset < part2offsets.length ); 42 | 43 | return [ part1, part2 ]; 44 | }; 45 | -------------------------------------------------------------------------------- /2017/js/day6.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day6 = function( input ) 2 | { 3 | input = input.split( /\s/ ).map( ( num ) => parseInt( num, 10 ) ); 4 | 5 | const duplicates = new Map(); 6 | let part1 = 0; 7 | let part2 = 0; 8 | let hit = ''; 9 | 10 | while( !duplicates.has( hit ) ) 11 | { 12 | duplicates.set( hit, part1++ ); 13 | 14 | let highestValue = -1; 15 | let highestIndex = -1; 16 | 17 | for( let i = 0; i < input.length; i++ ) 18 | { 19 | if( input[ i ] > highestValue ) 20 | { 21 | highestValue = input[ i ]; 22 | highestIndex = i; 23 | } 24 | } 25 | 26 | input[ highestIndex ] = 0; 27 | 28 | while( highestValue-- > 0 ) 29 | { 30 | input[ ++highestIndex % input.length ]++; 31 | } 32 | 33 | hit = input.join( ',' ); 34 | } 35 | 36 | part2 = part1 - duplicates.get( hit ); 37 | 38 | return [ part1, part2 ]; 39 | }; 40 | -------------------------------------------------------------------------------- /2017/js/day8.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day8 = function( input ) 2 | { 3 | input = input.split( /\n/ ); 4 | 5 | const Token = 6 | { 7 | Variable: 0, 8 | Modifier: 1, 9 | Value: 2, 10 | ConditionVariable: 4, 11 | Condition: 5, 12 | ConditionValue: 6, 13 | }; 14 | 15 | const registers = {}; 16 | let part2 = 0; 17 | 18 | const IsConditionSatisfied = ( variable, condition, value ) => 19 | { 20 | if( condition === '>' )return variable > value; 21 | if( condition === '<' )return variable < value; 22 | if( condition === '>=' )return variable >= value; 23 | if( condition === '<=' )return variable <= value; 24 | if( condition === '==' )return variable == value; 25 | if( condition === '!=' )return variable != value; 26 | 27 | }; 28 | 29 | input.forEach( ( line ) => 30 | { 31 | line = line.split( ' ' ); 32 | 33 | if( IsConditionSatisfied( 34 | registers[ line[ Token.ConditionVariable ] ] || 0, 35 | line[ Token.Condition ], 36 | line[ Token.ConditionValue ] 37 | ) ) 38 | { 39 | const variable = line[ Token.Variable ]; 40 | let value = registers[ variable ] || 0; 41 | 42 | if( line[ Token.Modifier ] === 'inc' ) 43 | { 44 | value += +line[ Token.Value ]; 45 | } 46 | else 47 | { 48 | value -= +line[ Token.Value ]; 49 | } 50 | 51 | if( part2 < value ) 52 | { 53 | part2 = value; 54 | } 55 | 56 | registers[ variable ] = value; 57 | } 58 | } ); 59 | 60 | return [ Math.max( ...Object.values( registers ) ), part2 ]; 61 | }; 62 | -------------------------------------------------------------------------------- /2017/js/day9.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day9 = function( input ) 2 | { 3 | let isGarbage = false; 4 | let totalScore = 0; 5 | let totalGarbage = 0; 6 | let groups = 0; 7 | 8 | for( let i = 0; i < input.length; i++ ) 9 | { 10 | const character = input[ i ]; 11 | 12 | // any character that comes after ! should be ignored 13 | if( character === '!' ) 14 | { 15 | i++; 16 | } 17 | // count the garbage 18 | else if( isGarbage ) 19 | { 20 | // garbage ends with > 21 | if( character === '>' ) 22 | { 23 | isGarbage = false; 24 | } 25 | else 26 | { 27 | totalGarbage++; 28 | } 29 | } 30 | // garbage begins with < 31 | else if( character === '<' ) 32 | { 33 | isGarbage = true; 34 | } 35 | // groups begin with { 36 | else if( character === '{' ) 37 | { 38 | totalScore += ++groups; 39 | } 40 | // groups end with } 41 | else if( character == '}' ) 42 | { 43 | --groups; 44 | } 45 | } 46 | 47 | return [ totalScore, totalGarbage ]; 48 | }; 49 | -------------------------------------------------------------------------------- /2018/js/day1.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day1 = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( x => +x ); 6 | 7 | let index = 0; 8 | let seenValue = 0; 9 | const seen = new Map(); 10 | 11 | do 12 | { 13 | seenValue += input[ index % input.length ]; 14 | index++; 15 | 16 | if( seen.has( seenValue ) ) 17 | { 18 | break; 19 | } 20 | 21 | seen.set( seenValue, true ); 22 | } 23 | while( true ); // eslint-disable-line no-constant-condition 24 | 25 | const sum = input.reduce( ( p, c ) => p + c, 0 ); 26 | 27 | return [ sum, seenValue ]; 28 | }; 29 | -------------------------------------------------------------------------------- /2018/js/day12.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day12 = ( input ) => 2 | { 3 | input = input.split( '\n' ); 4 | 5 | const rules = []; 6 | 7 | for( let i = 2; i < input.length; i++ ) 8 | { 9 | const rule = input[ i ].split( ' => ' ); 10 | 11 | if( rule[ 1 ] === '#' ) 12 | { 13 | rules.push( rule ); 14 | } 15 | } 16 | 17 | const leftPadding = 20; 18 | const sum = ( state ) => 19 | { 20 | let result = 0; 21 | 22 | for( const c in state ) 23 | { 24 | if( state[ c ] === '#' ) 25 | { 26 | result += c - leftPadding; 27 | } 28 | } 29 | 30 | return result; 31 | }; 32 | 33 | let state = '.'.repeat( leftPadding ) + input[ 0 ].substring( 15 ) + '.'.repeat( 300 ); 34 | state = state.split( '' ); 35 | 36 | let previousSum = 0; 37 | let i = 0; 38 | let part1 = 0; 39 | 40 | for( ; i < 200; i++ ) 41 | { 42 | const nextState = Array( state.length ).fill( '.' ); 43 | 44 | for( let c = 0; c < state.length; c++ ) 45 | { 46 | for( let r = 0; r < rules.length; r++ ) 47 | { 48 | let match = true; 49 | for( let x = 0; x < 5; x++ ) 50 | { 51 | if( state[ c + x ] !== rules[ r ][ 0 ][ x ] ) 52 | { 53 | match = false; 54 | break; 55 | } 56 | } 57 | 58 | if( match ) 59 | { 60 | nextState[ c + 2 ] = rules[ r ][ 1 ]; 61 | break; 62 | } 63 | } 64 | } 65 | 66 | const currentSum = sum( nextState ); 67 | 68 | if( previousSum + leftPadding === currentSum ) 69 | { 70 | break; 71 | } 72 | 73 | previousSum = currentSum; 74 | state = nextState; 75 | 76 | if( i === 19 ) 77 | { 78 | part1 = currentSum; 79 | } 80 | } 81 | 82 | const part2 = sum( state ) + ( ( 50000000000 - i ) * leftPadding ); 83 | 84 | return [ part1, part2 ]; 85 | }; 86 | -------------------------------------------------------------------------------- /2018/js/day2.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day2 = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( x => x.split( '' ) ); 6 | 7 | let part1twos = 0; 8 | let part1threes = 0; 9 | let part2; 10 | 11 | for( const id of input ) 12 | { 13 | const letters = new Map(); 14 | 15 | for( const letter of id ) 16 | { 17 | letters.set( letter, ( letters.get( letter ) || 0 ) + 1 ); 18 | } 19 | 20 | const values = Array.from( letters.values() ); 21 | 22 | part1twos += +values.includes( 2 ); 23 | part1threes += +values.includes( 3 ); 24 | } 25 | 26 | part2: 27 | for( const id of input ) 28 | { 29 | for( const id2 of input ) 30 | { 31 | let differences = 0; 32 | part2 = ''; 33 | 34 | for( let i = 0; i < id.length; i++ ) 35 | { 36 | if( id[ i ] !== id2[ i ] ) 37 | { 38 | differences++; 39 | } 40 | else 41 | { 42 | part2 += id[ i ]; 43 | } 44 | } 45 | 46 | if( differences === 1 ) 47 | { 48 | break part2; 49 | } 50 | } 51 | } 52 | 53 | return [ part1twos * part1threes, part2 ]; 54 | }; 55 | -------------------------------------------------------------------------------- /2018/js/day3.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day3 = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ); 5 | 6 | const stride = 1000; 7 | const grid = new Float32Array( stride * stride ); 8 | const claims = new Float32Array( stride * stride ); 9 | const claimed = new Set(); 10 | const parse = /^#([0-9]+) @ ([0-9]+),([0-9]+): ([0-9]+)x([0-9]+)$/; 11 | 12 | for( const line of input ) 13 | { 14 | const data = parse.exec( line ); 15 | const id = +data[ 1 ]; 16 | const x1 = +data[ 2 ]; 17 | const y1 = +data[ 3 ]; 18 | const width = +data[ 4 ]; 19 | const height = +data[ 5 ]; 20 | let overlapped = false; 21 | 22 | for( let x = x1; x < x1 + width; x++ ) 23 | { 24 | for( let y = y1; y < y1 + height; y++ ) 25 | { 26 | if( grid[ x * stride + y ] > 0 ) 27 | { 28 | overlapped = true; 29 | 30 | claimed.delete( claims[ x * stride + y ] ); 31 | } 32 | 33 | grid[ x * stride + y ]++; 34 | claims[ x * stride + y ] = id; 35 | } 36 | } 37 | 38 | if( !overlapped ) 39 | { 40 | claimed.add( id ); 41 | } 42 | } 43 | 44 | let overlaps = 0; 45 | 46 | for( let i = grid.length; i > 0; i-- ) 47 | { 48 | if( grid[ i ] > 1 ) 49 | { 50 | overlaps++; 51 | } 52 | } 53 | 54 | return [ overlaps, claimed.values().next().value ]; 55 | }; 56 | -------------------------------------------------------------------------------- /2018/js/day5.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day5 = ( input ) => 2 | { 3 | const reactions = []; 4 | 5 | for( let i = 65; i <= 90; i++ ) 6 | { 7 | const uppercase = String.fromCodePoint( i ); 8 | const lowercase = String.fromCodePoint( i + 32 ); 9 | 10 | reactions.push( uppercase + lowercase ); 11 | reactions.push( lowercase + uppercase ); 12 | } 13 | 14 | const reduceReactions = new RegExp( reactions.join( '|' ), 'g' ); 15 | const reducedLengths = []; 16 | 17 | // 64 is @ which doesn't actually replace anything and we use that for part 1 18 | for( let i = 64; i <= 90; i++ ) 19 | { 20 | const uppercase = String.fromCodePoint( i ); 21 | 22 | let previous; 23 | let current = input.replace( new RegExp( uppercase, 'ig' ), '' ); 24 | 25 | do 26 | { 27 | previous = current; 28 | current = current.replace( reduceReactions, '' ); 29 | } 30 | while( previous !== current ); 31 | 32 | reducedLengths.push( current.length ); 33 | 34 | // Pass part1 output into part2 35 | if( i === 64 ) 36 | { 37 | input = current; 38 | } 39 | } 40 | 41 | return [ reducedLengths[ 0 ], Math.min( ...reducedLengths ) ]; 42 | }; 43 | -------------------------------------------------------------------------------- /2018/js/day7.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day7 = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( l => 6 | { 7 | l = l.split( ' ' ); 8 | 9 | return [ l[ 1 ], l[ 7 ] ]; 10 | } ); 11 | 12 | let graph = new Map(); 13 | 14 | for( const pair of input ) 15 | { 16 | if( !graph.has( pair[ 0 ] ) ) 17 | { 18 | graph.set( pair[ 0 ], new Set() ); 19 | } 20 | 21 | if( !graph.has( pair[ 1 ] ) ) 22 | { 23 | graph.set( pair[ 1 ], new Set() ); 24 | } 25 | 26 | graph.get( pair[ 0 ] ).add( pair[ 1 ] ); 27 | } 28 | 29 | let part1 = ''; 30 | graph = new Map( [ ...graph.entries() ].sort() ); 31 | 32 | while( graph.size > 0 ) 33 | { 34 | for( const set of graph ) 35 | { 36 | let depends = false; 37 | 38 | for( const set2 of graph ) 39 | { 40 | if( set2[ 1 ].has( set[ 0 ] ) ) 41 | { 42 | depends = true; 43 | break; 44 | } 45 | } 46 | 47 | if( !depends ) 48 | { 49 | part1 += set[ 0 ]; 50 | graph.delete( set[ 0 ] ); 51 | break; 52 | } 53 | } 54 | } 55 | 56 | return [ part1, 0 ]; 57 | }; 58 | -------------------------------------------------------------------------------- /2018/js/day8.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day8 = ( input ) => 2 | { 3 | input = input.split( ' ' ).map( x => +x ); 4 | 5 | let part1 = 0; 6 | let index = 0; 7 | 8 | const process = () => 9 | { 10 | const childrenSize = input[ index++ ]; 11 | const metadataSize = input[ index++ ]; 12 | const values = []; 13 | let value = 0; 14 | 15 | for( let i = childrenSize; i > 0; i-- ) 16 | { 17 | values.push( process() ); 18 | } 19 | 20 | const metadata = input.slice( index, index += metadataSize ); 21 | const metadataSum = metadata.reduce( ( a, b ) => a + b, 0 ); 22 | 23 | part1 += metadataSum; 24 | 25 | if( childrenSize > 0 ) 26 | { 27 | for( const i of metadata ) 28 | { 29 | value += values[ i - 1 ] || 0; 30 | } 31 | } 32 | else 33 | { 34 | value = metadataSum; 35 | } 36 | 37 | return value; 38 | }; 39 | 40 | const part2 = process(); 41 | 42 | return [ part1, part2 ]; 43 | }; 44 | -------------------------------------------------------------------------------- /2018/js/day9.js: -------------------------------------------------------------------------------- 1 | window.AdventOfCode.Day9 = ( input ) => 2 | { 3 | input = input.match( /([0-9]+)/g ); 4 | 5 | const players = +input[ 0 ]; 6 | const lastMarble = +input[ 1 ]; 7 | 8 | const placeMarble = ( points, marble ) => 9 | { 10 | const obj = 11 | { 12 | points: points, 13 | prev: marble, 14 | next: marble.next, 15 | }; 16 | marble.next.prev = obj; 17 | marble.next = obj; 18 | return obj; 19 | }; 20 | 21 | const play = function( players, lastMarble ) 22 | { 23 | const scores = Array( players ).fill( 0 ); 24 | let player = 0; 25 | let current = 26 | { 27 | points: 0, 28 | }; 29 | current.next = current; 30 | current.prev = current; 31 | 32 | for( let marble = 1; marble <= lastMarble; marble++ ) 33 | { 34 | if( marble % 23 !== 0 ) 35 | { 36 | current = placeMarble( marble, current.next ); 37 | } 38 | else 39 | { 40 | current = current.prev.prev.prev.prev.prev.prev; 41 | 42 | scores[ player ] += marble + current.prev.points; 43 | 44 | current.prev.prev.next = current; 45 | current.prev = current.prev.prev; 46 | } 47 | 48 | player = ++player % players; 49 | } 50 | 51 | return Math.max( ...scores ); 52 | }; 53 | 54 | return [ 55 | play( players, lastMarble ), 56 | play( players, lastMarble * 100 ) 57 | ]; 58 | }; 59 | -------------------------------------------------------------------------------- /2019/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | process.chdir( __dirname ); 4 | 5 | const { readFileSync } = require( 'fs' ); 6 | const day = parseInt( process.argv[ 2 ], 10 ); 7 | 8 | if( isNaN( day ) ) 9 | { 10 | console.error( 'Usage: node index.js [input]' ); 11 | console.error( 'If input is not specified, reads from data/day%.txt' ); 12 | process.exit( 1 ); 13 | } 14 | 15 | let runs = 1; 16 | 17 | if( process.argv[ 3 ] === 'bench' ) 18 | { 19 | delete process.argv[ 3 ]; 20 | runs = parseInt( process.argv[ 4 ], 10 ) || 1000; 21 | } 22 | 23 | let input = process.argv[ 3 ] || readFileSync( `./data/day${day}.txt` ).toString(); 24 | input = input.replace( /\r/g, '' ).trim(); 25 | 26 | let result; 27 | const solution = require( `./js/day${day}.js` ); 28 | const startTime = process.hrtime.bigint(); 29 | 30 | for( let i = 0; i < runs; i++ ) 31 | { 32 | result = solution( input ); 33 | } 34 | 35 | const endTime = process.hrtime.bigint(); 36 | 37 | console.log( 'Part 1: \x1b[32m%s\x1b[0m', result[ 0 ] ); 38 | console.log( 'Part 2: \x1b[32m%s\x1b[0m', result[ 1 ] ); 39 | 40 | const time = Number( endTime - startTime ) / 1e9 / runs; 41 | 42 | if( runs > 1 ) 43 | { 44 | console.log( `Time : \x1b[34m${time.toFixed( 6 )}\x1b[0m seconds average for \x1b[34m${runs}\x1b[0m runs` ); 45 | } 46 | else 47 | { 48 | console.log( `Time : \x1b[34m${time.toFixed( 6 )}\x1b[0m seconds` ); 49 | } 50 | -------------------------------------------------------------------------------- /2019/js/day1.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( x => Math.floor( x / 3 ) - 2 ); 6 | 7 | const part1 = input.reduce( ( x, y ) => x + y, 0 ); 8 | let part2 = part1; 9 | 10 | do 11 | { 12 | input = input.map( x => Math.floor( x / 3 ) - 2 ); 13 | part2 += input.reduce( ( x, y ) => y > 0 ? x + y : x, 0 ); 14 | } 15 | while( input.some( x => x > 0 ) ); 16 | 17 | return [ part1, part2 ]; 18 | }; 19 | -------------------------------------------------------------------------------- /2019/js/day11.js: -------------------------------------------------------------------------------- 1 | const IntCode = require( '../intcode.js' ); 2 | 3 | module.exports = ( input ) => 4 | { 5 | input = input 6 | .split( ',' ) 7 | .map( x => +x ); 8 | 9 | let part1 = 0; 10 | let grid = robot( input ); 11 | 12 | for( const key in grid ) 13 | { 14 | for( const key2 in grid[ key ] ) // eslint-disable-line no-unused-vars 15 | { 16 | part1++; 17 | } 18 | } 19 | 20 | const part2 = []; 21 | grid = robot( input, 1 ); 22 | 23 | for( const key in grid ) 24 | { 25 | part2.push( '\n' ); 26 | 27 | for( let i = 0; i < grid[ key ].length; i++ ) 28 | { 29 | part2.push( grid[ key ][ i ] === 1 ? '00' : ' ' ); 30 | } 31 | } 32 | 33 | return [ part1, part2.join( '' ) ]; 34 | }; 35 | 36 | function robot( input, defaultColor = 0 ) 37 | { 38 | let x = 0; 39 | let y = 0; 40 | let rotation = 0; 41 | const grid = []; 42 | 43 | const directions = 44 | [ 45 | { x: 0 , y: -1 }, 46 | { x: 1 , y: 0 }, 47 | { x: 0 , y: 1 }, 48 | { x: -1, y: 0 }, 49 | ]; 50 | 51 | const stateMachine = new IntCode( input ); 52 | 53 | do 54 | { 55 | if( !grid[ y ] ) 56 | { 57 | grid[ y ] = []; 58 | } 59 | 60 | const [ color, turn ] = stateMachine.execute( [ grid[ y ][ x ] || defaultColor ] ); 61 | 62 | grid[ y ][ x ] = color; 63 | 64 | rotation = rotation + ( turn ? 1 : -1 ); 65 | rotation = ( ( rotation % 4 ) + 4 ) % 4; 66 | 67 | const direction = directions[ rotation ]; 68 | x += direction.x; 69 | y += direction.y; 70 | } 71 | while( !stateMachine.halted ); 72 | 73 | return grid; 74 | } 75 | -------------------------------------------------------------------------------- /2019/js/day13.js: -------------------------------------------------------------------------------- 1 | const IntCode = require( '../intcode.js' ); 2 | 3 | module.exports = ( input ) => 4 | { 5 | input = input 6 | .split( ',' ) 7 | .map( x => +x ); 8 | 9 | input[ 0 ] = 2; 10 | const stateMachine = new IntCode( input ); 11 | 12 | let part1 = 0; 13 | let part2 = 0; 14 | let ballX = 0; 15 | let paddleX = 0; 16 | let nextInput = 0; 17 | 18 | do 19 | { 20 | const output = stateMachine.execute( [ nextInput ] ); 21 | 22 | for( let i = 0; i < output.length; i += 3 ) 23 | { 24 | const x = output[ i ]; 25 | const y = output[ i + 1 ]; 26 | const tile = output[ i + 2 ]; 27 | 28 | if( x === -1 && y === 0 ) 29 | { 30 | part2 = tile; 31 | } 32 | else if( tile === 2 ) 33 | { 34 | part1++; 35 | } 36 | else if( tile === 3 ) 37 | { 38 | paddleX = x; 39 | } 40 | else if( tile === 4 ) 41 | { 42 | ballX = x; 43 | } 44 | } 45 | 46 | if( paddleX < ballX ) 47 | { 48 | nextInput = 1; 49 | paddleX++; 50 | } 51 | else if( paddleX > ballX ) 52 | { 53 | nextInput = -1; 54 | paddleX--; 55 | } 56 | else 57 | { 58 | nextInput = 0; 59 | } 60 | } 61 | while( !stateMachine.halted ); 62 | 63 | return [ part1, part2 ]; 64 | }; 65 | -------------------------------------------------------------------------------- /2019/js/day2.js: -------------------------------------------------------------------------------- 1 | const IntCode = require( '../intcode.js' ); 2 | 3 | module.exports = ( input ) => 4 | { 5 | input = input 6 | .split( ',' ) 7 | .map( x => +x ); 8 | 9 | input[ 1 ] = 12; 10 | input[ 2 ] = 2; 11 | const stateMachine = new IntCode( input ); 12 | stateMachine.execute(); 13 | const part1 = stateMachine.memory[ 0 ]; 14 | let part2 = 0; 15 | 16 | bruteforce: 17 | for( let y = 0; y <= input.length; y++ ) 18 | { 19 | input[ 1 ] = y; 20 | 21 | for( let x = 0; x <= input.length; x++ ) 22 | { 23 | input[ 2 ] = x; 24 | 25 | const stateMachine = new IntCode( input ); 26 | stateMachine.execute(); 27 | 28 | if( stateMachine.memory[ 0 ] === 19690720 ) 29 | { 30 | part2 = 100 * y + x; 31 | break bruteforce; 32 | } 33 | } 34 | } 35 | 36 | return [ part1, part2 ]; 37 | }; 38 | -------------------------------------------------------------------------------- /2019/js/day4.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( '-' ); 4 | let start = +input[ 0 ]; 5 | const end = +input[ 1 ]; 6 | let part1 = 0; 7 | let part2 = 0; 8 | 9 | do 10 | { 11 | const pass = start.toString(); 12 | part1 += checkPassword( pass ); 13 | part2 += checkPassword2( pass ); 14 | } 15 | while( ++start < end ); 16 | 17 | return [ part1, part2 ]; 18 | }; 19 | 20 | function checkPassword( pass ) 21 | { 22 | let hasDouble = 0; 23 | 24 | for( let i = 1; i < 6; i++ ) 25 | { 26 | const a = pass[ i - 1 ]; 27 | const b = pass[ i ]; 28 | 29 | if( a > b ) 30 | { 31 | return 0; 32 | } 33 | 34 | hasDouble |= a === b; 35 | } 36 | 37 | return hasDouble; 38 | } 39 | 40 | function checkPassword2( pass ) 41 | { 42 | let hasDouble = 0; 43 | let prev = -1; 44 | 45 | for( let i = 1; i < 6; i++ ) 46 | { 47 | const a = pass[ i - 1 ]; 48 | const b = pass[ i ]; 49 | 50 | if( a > b ) 51 | { 52 | return 0; 53 | } 54 | 55 | hasDouble |= a === b && b !== pass[ i + 1 ] && prev !== a; 56 | prev = a; 57 | } 58 | 59 | return hasDouble; 60 | } 61 | -------------------------------------------------------------------------------- /2019/js/day5.js: -------------------------------------------------------------------------------- 1 | const IntCode = require( '../intcode.js' ); 2 | 3 | module.exports = ( input ) => 4 | { 5 | input = input 6 | .split( ',' ) 7 | .map( x => +x ); 8 | 9 | const part1 = new IntCode( input ).execute( [ 1 ] ).pop(); 10 | const part2 = new IntCode( input ).execute( [ 5 ] ).pop(); 11 | 12 | return [ part1, part2 ]; 13 | }; 14 | -------------------------------------------------------------------------------- /2019/js/day6.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | const objects = new Map(); 4 | objects.set( 'COM', null ); 5 | 6 | input 7 | .split( '\n' ) 8 | .map( x => x.split( ')' ) ) 9 | .forEach( ( [ a, b ] ) => objects.set( b, a ) ); 10 | 11 | const orbits = ( obj ) => obj ? 1 + orbits( objects.get( obj ) ) : 0; 12 | const part1 = Array.from( objects.keys() ) 13 | .reduce( ( total, obj ) => total + orbits( objects.get( obj ) ), 0 ); 14 | 15 | const chain = ( obj, links ) => obj ? chain( objects.get( obj ), [ ...links, obj ] ) : links; 16 | const transfer = ( obj, path, depth ) => 17 | { 18 | const index = path.indexOf( obj ); 19 | 20 | if( index > -1 ) 21 | { 22 | return depth + index; 23 | } 24 | 25 | return transfer( objects.get( obj ), path, depth + 1 ); 26 | }; 27 | const part2 = transfer( objects.get( 'SAN' ), chain( objects.get( 'YOU' ), [] ), 0 ); 28 | 29 | return [ part1, part2 ]; 30 | }; 31 | -------------------------------------------------------------------------------- /2019/js/day7.js: -------------------------------------------------------------------------------- 1 | const IntCode = require( '../intcode.js' ); 2 | 3 | module.exports = ( input ) => 4 | { 5 | input = input 6 | .split( ',' ) 7 | .map( x => +x ); 8 | 9 | let part1 = 0; 10 | const part2 = 0; 11 | const phases = permutator( [ 0, 1, 2, 3, 4 ] ); 12 | 13 | for( const phase of phases ) 14 | { 15 | let signal = 0; 16 | 17 | for( let i = 0; i < 5; i++ ) 18 | { 19 | const ioInput = [ phase[ i ], signal ]; 20 | signal = new IntCode( input ).execute( ioInput ).pop(); 21 | } 22 | 23 | if( part1 < signal ) 24 | { 25 | part1 = signal; 26 | } 27 | } 28 | 29 | return [ part1, part2 ]; 30 | }; 31 | 32 | function permutator( inputArr ) 33 | { 34 | const result = []; 35 | 36 | const permute = ( arr, m = [] ) => 37 | { 38 | if( arr.length === 0 ) 39 | { 40 | result.push( m ); 41 | } 42 | else 43 | { 44 | for( let i = 0; i < arr.length; i++ ) 45 | { 46 | const curr = arr.slice(); 47 | const next = curr.splice( i, 1 ); 48 | permute( curr.slice(), m.concat( next ) ); 49 | } 50 | } 51 | }; 52 | 53 | permute( inputArr ); 54 | 55 | return result; 56 | } 57 | -------------------------------------------------------------------------------- /2019/js/day8.js: -------------------------------------------------------------------------------- 1 | const COLOR_BLACK = 0; 2 | const COLOR_TRANSPARENT = 2; 3 | 4 | module.exports = ( input ) => 5 | { 6 | const w = 25; 7 | const h = 6; 8 | const stride = w * h; 9 | const layersCount = input.length / stride; 10 | const layers = new Array( layersCount ); 11 | const pixels = new Array( stride ).fill( COLOR_TRANSPARENT ); 12 | let lowestCounts = [ Number.MAX_SAFE_INTEGER, 0, 0 ]; 13 | 14 | for( let i = 0, o = 0; i < layersCount; i++, o += stride ) 15 | { 16 | layers[ i ] = input.substr( o, stride ); 17 | } 18 | 19 | for( const layer of layers ) 20 | { 21 | const counts = [ 0, 0, 0 ]; 22 | 23 | for( let i = 0; i < stride; i++ ) 24 | { 25 | const pixel = +layer[ i ]; 26 | counts[ pixel ]++; 27 | 28 | if( pixels[ i ] === COLOR_TRANSPARENT ) 29 | { 30 | pixels[ i ] = pixel; 31 | } 32 | } 33 | 34 | if( lowestCounts[ 0 ] > counts[ 0 ] ) 35 | { 36 | lowestCounts = counts; 37 | } 38 | } 39 | 40 | const part1 = lowestCounts[ 1 ] * lowestCounts[ 2 ]; 41 | const part2 = []; 42 | 43 | for( let i = 0; i < stride; i++ ) 44 | { 45 | if( i % w === 0 ) 46 | { 47 | part2.push( '\n' ); 48 | } 49 | 50 | part2.push( pixels[ i ] === COLOR_BLACK ? ' ' : '00' ); 51 | } 52 | 53 | return [ part1, part2.join( '' ) ]; 54 | }; 55 | -------------------------------------------------------------------------------- /2019/js/day9.js: -------------------------------------------------------------------------------- 1 | const IntCode = require( '../intcode.js' ); 2 | 3 | module.exports = ( input ) => 4 | { 5 | input = input 6 | .split( ',' ) 7 | .map( x => +x ); 8 | 9 | const part1 = new IntCode( input ).execute( [ 1 ] ).pop(); 10 | const part2 = new IntCode( input ).execute( [ 2 ] ).pop(); 11 | 12 | return [ part1, part2 ]; 13 | }; 14 | -------------------------------------------------------------------------------- /2019/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "fix": "eslint --fix .", 4 | "test": "eslint . && ava" 5 | }, 6 | "devDependencies": { 7 | "ava": "^3.13.0", 8 | "eslint": "^7.11.0" 9 | }, 10 | "ava": { 11 | "files": [ 12 | "test.js" 13 | ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2019/test.js: -------------------------------------------------------------------------------- 1 | const test = require( 'ava' ); 2 | const { readFileSync } = require( 'fs' ); 3 | 4 | process.chdir( __dirname ); 5 | 6 | test( '2019', t => 7 | { 8 | assert( t, 1, 3311492, 4964376 ); 9 | assert( t, 2, 3058646, 8976 ); 10 | assert( t, 4, 1955, 1319 ); 11 | assert( t, 5, 13087969, 14110739 ); 12 | assert( t, 6, 106065, 253 ); 13 | assert( t, 7, 87138, 0 ); 14 | assert( t, 8, 1965, ` 15 | 0000 00000000 00 00 0000 00 00 16 | 00 00 00 00 00 00 00 00 17 | 00 00 0000 00 00 00 18 | 00 0000 00 00 00 00 00 19 | 00 00 00 00 00 00 00 00 20 | 000000 00000000 00 00 0000 00 ` ); 21 | assert( t, 9, 4288078517, 69256 ); 22 | assert( t, 11, 2226, ` 23 | 00 00 000000 0000 00 00000000 00 00 00 00000000 24 | 00 00 00 00 00 00 00 00 00 00 00 00 25 | 00000000 000000 00 00 00 0000 00 000000 26 | 00 00 00 00 00 0000 00 00 00 00 00 00 27 | 00 00 00 00 00 00 00 00 00 00 00 00 28 | 00 00 000000 000000 00000000 00000000 00 00 00000000 00 ` ); 29 | assert( t, 13, 296, 13824 ); 30 | } ); 31 | 32 | function assert( t, day, answer1, answer2 ) 33 | { 34 | let input = readFileSync( `./data/day${day}.txt` ).toString(); 35 | input = input.replace( /\r/g, '' ).trim(); 36 | 37 | const solution = require( `./js/day${day}.js` ); 38 | const result = solution( input ); 39 | 40 | t.is( result[ 0 ], answer1 ); 41 | t.is( result[ 1 ], answer2 ); 42 | } 43 | -------------------------------------------------------------------------------- /2020/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | process.chdir( __dirname ); 4 | 5 | const { readFileSync } = require( 'fs' ); 6 | const day = parseInt( process.argv[ 2 ], 10 ); 7 | 8 | if( isNaN( day ) ) 9 | { 10 | console.error( 'Usage: node index.js [input]' ); 11 | console.error( 'If input is not specified, reads from data/day%.txt' ); 12 | process.exit( 1 ); 13 | } 14 | 15 | let runs = 1; 16 | 17 | if( process.argv[ 3 ] === 'bench' ) 18 | { 19 | delete process.argv[ 3 ]; 20 | runs = parseInt( process.argv[ 4 ], 10 ) || 1000; 21 | } 22 | 23 | let input = process.argv[ 3 ] || readFileSync( `./data/day${day}.txt` ).toString(); 24 | input = input.replace( /\r/g, '' ).trim(); 25 | 26 | let result; 27 | const solution = require( `./js/day${day}.js` ); 28 | const startTime = process.hrtime.bigint(); 29 | 30 | for( let i = 0; i < runs; i++ ) 31 | { 32 | result = solution( input ); 33 | } 34 | 35 | const endTime = process.hrtime.bigint(); 36 | 37 | console.log( 'Part 1: \x1b[32m%s\x1b[0m', result[ 0 ] ); 38 | console.log( 'Part 2: \x1b[32m%s\x1b[0m', result[ 1 ] ); 39 | 40 | const time = Number( endTime - startTime ) / 1e9 / runs; 41 | 42 | if( runs > 1 ) 43 | { 44 | console.log( `Time : \x1b[34m${time.toFixed( 6 )}\x1b[0m seconds average for \x1b[34m${runs}\x1b[0m runs` ); 45 | } 46 | else 47 | { 48 | console.log( `Time : \x1b[34m${time.toFixed( 6 )}\x1b[0m seconds` ); 49 | } 50 | -------------------------------------------------------------------------------- /2020/js/day1.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( x => parseInt( x, 10 ) ); 6 | 7 | let part1 = 0; 8 | let part2 = 0; 9 | 10 | for( let a = 0; a < input.length; a++ ) 11 | { 12 | for( let b = a + 1; b < input.length; b++ ) 13 | { 14 | if( !part1 && input[ a ] + input[ b ] === 2020 ) 15 | { 16 | part1 = input[ a ] * input[ b ]; 17 | } 18 | 19 | for( let c = b + 1; c < input.length; c++ ) 20 | { 21 | if( input[ a ] + input[ b ] + input[ c ] === 2020 ) 22 | { 23 | part2 = input[ a ] * input[ b ] * input[ c ]; 24 | } 25 | } 26 | } 27 | } 28 | 29 | return [ part1, part2 ]; 30 | }; 31 | -------------------------------------------------------------------------------- /2020/js/day10.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( x => parseInt( x, 10 ) ) 6 | .sort( ( a, b ) => a - b ); 7 | 8 | let current = 0; 9 | const diffs = 10 | [ 11 | 0, 12 | 0, 13 | 0, 14 | 1, // 3 higher than the highest-rated adapter. 15 | ]; 16 | const paths = 17 | [ 18 | 1, // device's built-in 19 | ]; 20 | 21 | for( const adapter of input ) 22 | { 23 | diffs[ adapter - current ]++; 24 | current = adapter; 25 | 26 | paths[ adapter ] = 27 | ( paths[ adapter - 3 ] || 0 ) + 28 | ( paths[ adapter - 2 ] || 0 ) + 29 | ( paths[ adapter - 1 ] || 0 ); 30 | } 31 | 32 | const part1 = diffs[ 3 ] * diffs[ 1 ]; 33 | const part2 = paths[ paths.length - 1 ]; 34 | 35 | return [ part1, part2 ]; 36 | }; 37 | -------------------------------------------------------------------------------- /2020/js/day12.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( x => 6 | { 7 | return { 8 | action: x[ 0 ], 9 | value: parseInt( x.substring( 1 ), 10 ) 10 | }; 11 | } ); 12 | 13 | // Part 1 14 | let x = 0; 15 | let y = 0; 16 | let wx = 1; 17 | let wy = 0; 18 | 19 | function solve() 20 | { 21 | for( const { action, value } of input ) 22 | { 23 | actions[ action ]( value ); 24 | } 25 | 26 | return Math.abs( x ) + Math.abs( y ); 27 | } 28 | 29 | const actions = 30 | { 31 | N: value => y += value, 32 | E: value => x += value, 33 | S: value => y -= value, 34 | W: value => x -= value, 35 | L: value => 36 | { 37 | for( let angle = value; angle > 0; angle -= 90 ) [ wx, wy ] = [ -wy, wx ]; 38 | }, 39 | R: value => 40 | { 41 | for( let angle = value; angle > 0; angle -= 90 ) [ wx, wy ] = [ wy, -wx ]; 42 | }, 43 | F: value => 44 | { 45 | x += wx * value; y += wy * value; 46 | }, 47 | }; 48 | 49 | const part1 = solve(); 50 | 51 | // Part 2 52 | x = 0; 53 | y = 0; 54 | wx = 10; 55 | wy = 1; 56 | 57 | actions.N = value => wy += value; 58 | actions.E = value => wx += value; 59 | actions.S = value => wy -= value; 60 | actions.W = value => wx -= value; 61 | 62 | const part2 = solve(); 63 | 64 | return [ part1, part2 ]; 65 | }; 66 | -------------------------------------------------------------------------------- /2020/js/day13.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( "\n" ); 4 | 5 | const timestamp = parseInt( input[ 0 ], 10 ); 6 | const buses = input[ 1 ] 7 | .split( ',' ) 8 | .map( ( bus, i ) => bus === 'x' ? null : { bus: parseInt( bus, 10 ), index: i } ) 9 | .filter( x => x !== null ); 10 | 11 | let time = Number.MAX_SAFE_INTEGER; 12 | let multiplier = null; 13 | let part1 = 0; 14 | let part2 = 0; 15 | 16 | for( const bus of buses ) 17 | { 18 | const delay = bus.bus - ( timestamp % bus.bus ); 19 | 20 | if( time > delay ) 21 | { 22 | time = delay; 23 | part1 = delay * bus.bus; 24 | } 25 | 26 | if( multiplier === null ) 27 | { 28 | multiplier = bus.bus; 29 | continue; 30 | } 31 | 32 | while( true ) // eslint-disable-line 33 | { 34 | if( ( part2 + bus.index ) % bus.bus === 0 ) 35 | { 36 | multiplier *= bus.bus; 37 | break; 38 | } 39 | 40 | part2 += multiplier; 41 | } 42 | } 43 | 44 | return [ part1, part2 ]; 45 | }; 46 | -------------------------------------------------------------------------------- /2020/js/day14.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( "\n" ); 4 | 5 | let mask; 6 | let mask1; 7 | let mask2; 8 | const memoryP1 = {}; 9 | const memoryP2 = {}; 10 | 11 | for( const line of input ) 12 | { 13 | if( line[ 1 ] === 'a' ) // mask 14 | { 15 | mask = line.match( /mask = (?.+)/ ).groups.mask; 16 | mask1 = BigInt( '0b' + mask.replaceAll( 'X', 1 ) ); 17 | mask2 = BigInt( '0b' + mask.replaceAll( 'X', 0 ) ); 18 | mask = mask.split( '' ); 19 | } 20 | else // mem 21 | { 22 | const mem = line.match( /mem\[(?\d+)] = (?\d+)/ ).groups; 23 | const addr = Number( mem.addr ); 24 | const value = BigInt( mem.value ); 25 | 26 | // part 1 27 | memoryP1[ addr ] = value & mask1 | mask2; 28 | 29 | // part 2 30 | const paddedAddr = addr.toString( 2 ).padStart( 36, '0' ); 31 | let addrs = [ 0n ]; 32 | 33 | mask.forEach( ( bit, index ) => 34 | { 35 | addrs = addrs.map( v => v << 1n ); 36 | 37 | if( bit === 'X' ) 38 | { 39 | addrs = addrs.concat( addrs.map( v => v | 1n ) ); 40 | } 41 | else if( bit === '1' || paddedAddr[ index ] === '1' ) 42 | { 43 | addrs = addrs.map( v => v | 1n ); 44 | } 45 | } ); 46 | 47 | for( const addr of addrs ) 48 | { 49 | memoryP2[ addr ] = value; 50 | } 51 | } 52 | } 53 | 54 | const bigSum = input => Number( Object.values( input ).reduce( ( a, b ) => a + b, 0n ) ); 55 | const part1 = bigSum( memoryP1 ); 56 | const part2 = bigSum( memoryP2 ); 57 | 58 | return [ part1, part2 ]; 59 | }; 60 | -------------------------------------------------------------------------------- /2020/js/day15.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( ',' ).map( x => parseInt( x, 10 ) ); 4 | 5 | const memory = new Int32Array( 30000000 ).fill( -1, 0, 30000000 ); 6 | let lastNumber = 0; 7 | let newNumber = 0; 8 | let part1 = 0; 9 | let part2 = 0; 10 | 11 | for( let i = 0; i < input.length; i++ ) 12 | { 13 | memory[ input[ i ] ] = i; 14 | } 15 | 16 | for( let i = input.length; i < 30000000; i++ ) 17 | { 18 | lastNumber = newNumber; 19 | const seen = memory[ newNumber ]; 20 | 21 | if( seen > -1 ) 22 | { 23 | newNumber = i - seen; 24 | } 25 | else 26 | { 27 | newNumber = 0; 28 | } 29 | 30 | memory[ lastNumber ] = i; 31 | 32 | if( i === 2019 ) 33 | { 34 | part1 = lastNumber; 35 | } 36 | } 37 | 38 | part2 = lastNumber; 39 | 40 | return [ part1, part2 ]; 41 | }; 42 | -------------------------------------------------------------------------------- /2020/js/day18.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( '\n' );//.map( l => l.replaceAll( ' ', '' ) ); 4 | 5 | function createEval1( expr ) 6 | { 7 | const newExpr = expr.replace( /(\d+)/g, '$1)' ); 8 | return '('.repeat( newExpr.match( /\)/g ).length ) + newExpr; 9 | } 10 | 11 | function createEval2( expr ) 12 | { 13 | return '((' + expr 14 | .replaceAll( '(', '(((' ) 15 | .replaceAll( ')', ')))' ) 16 | .replaceAll( '+', ')+(' ) 17 | .replaceAll( '*', '))*((' ) 18 | + '))'; 19 | } 20 | 21 | let part1 = 0; 22 | 23 | for( let line of input ) 24 | { 25 | do 26 | { 27 | const parenthesis = /\((?[^()]+)\)/.exec( line ); 28 | 29 | if( !parenthesis ) 30 | { 31 | break; 32 | } 33 | 34 | line = 35 | line.substr( 0, parenthesis.index ) + 36 | eval( createEval1( parenthesis.groups.expr ) ) + 37 | line.substr( parenthesis.index + parenthesis.groups.expr.length + 2 ); 38 | } 39 | while( true ); // eslint-disable-line 40 | 41 | part1 += eval( createEval1( line ) ); 42 | } 43 | 44 | const p2expr = []; 45 | 46 | for( const expr of input ) 47 | { 48 | p2expr.push( createEval2( expr ) ); 49 | } 50 | 51 | const part2 = eval( p2expr.join( '+' ) ); 52 | 53 | return [ part1, part2 ]; 54 | }; 55 | -------------------------------------------------------------------------------- /2020/js/day2.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( x => x.match( /(?\d+)-(?\d+) (?[a-z]+): (?.+)/ ).groups ); 6 | 7 | let part1 = 0; 8 | let part2 = 0; 9 | 10 | for( const pass of input ) 11 | { 12 | const a = parseInt( pass.min, 10 ); 13 | const b = parseInt( pass.max, 10 ); 14 | 15 | let matches = 0; 16 | 17 | for( let i = 0; i < pass.password.length; i++ ) 18 | { 19 | if( pass.password[ i ] === pass.letter ) 20 | { 21 | matches++; 22 | } 23 | } 24 | 25 | if( matches >= a && matches <= b ) 26 | { 27 | part1++; 28 | } 29 | 30 | const ap = pass.password[ a - 1 ]; 31 | const bp = pass.password[ b - 1 ]; 32 | 33 | if( ap !== bp && ( ap === pass.letter || bp === pass.letter ) ) 34 | { 35 | part2++; 36 | } 37 | } 38 | 39 | return [ part1, part2 ]; 40 | }; 41 | -------------------------------------------------------------------------------- /2020/js/day23.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( '' ).map( x => parseInt( x, 10 ) ); 4 | 5 | function solve( max, iterations ) 6 | { 7 | const cups = new Int32Array( max + 1 ); 8 | 9 | for( let i = 0; i < input.length - 1; i++ ) 10 | { 11 | cups[ input[ i ] ] = input[ i + 1 ]; 12 | } 13 | 14 | let prev = input[ input.length - 1 ]; 15 | 16 | if( max > 10 ) // this is dumb 17 | { 18 | for( let i = input.length + 1; i <= max; i++ ) 19 | { 20 | cups[ prev ] = i; 21 | prev = i; 22 | } 23 | 24 | cups[ max ] = input[ 0 ]; 25 | } 26 | else 27 | { 28 | cups[ prev ] = input[ 0 ]; 29 | } 30 | 31 | let currentCup = input[ 0 ]; 32 | 33 | for( let i = 0; i < iterations; i++ ) 34 | { 35 | let nextCup = currentCup; 36 | const cup1 = cups[ currentCup ]; 37 | const cup2 = cups[ cup1 ]; 38 | const cup3 = cups[ cup2 ]; 39 | 40 | do 41 | { 42 | if( --nextCup === 0 ) 43 | { 44 | nextCup = max; 45 | } 46 | } 47 | while( cup1 === nextCup || cup2 === nextCup || cup3 === nextCup ); 48 | 49 | cups[ currentCup ] = cups[ cup3 ]; 50 | cups[ cup3 ] = cups[ nextCup ]; 51 | cups[ nextCup ] = cup1; 52 | currentCup = cups[ currentCup ]; 53 | } 54 | 55 | return cups; 56 | } 57 | 58 | let cups = solve( 9, 100 ); 59 | let part1 = 0; 60 | let current = cups[ 1 ]; 61 | 62 | for( let i = 0; i < input.length - 1; ++i ) 63 | { 64 | part1 += Math.pow( 10, input.length - i - 2 ) * current; 65 | current = cups[ current ]; 66 | } 67 | 68 | cups = solve( 1000000, 10000000 ); 69 | const part2 = cups[ 1 ] * cups[ cups[ 1 ] ]; 70 | 71 | return [ part1, part2 ]; 72 | }; 73 | -------------------------------------------------------------------------------- /2020/js/day25.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( '\n' ).map( x => parseInt( x, 10 ) ); 4 | 5 | const [ card, door ] = input; 6 | 7 | let part1 = 1; 8 | let door2 = 1; 9 | 10 | while( door2 !== door ) 11 | { 12 | door2 = ( door2 * 7 ) % 20201227; 13 | part1 = ( part1 * card ) % 20201227; 14 | } 15 | 16 | return [ part1, 0 ]; 17 | }; 18 | -------------------------------------------------------------------------------- /2020/js/day3.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( '\n' ).map( row => row.split( '' ).map( cell => cell === '#' ) ); 4 | 5 | const width = input[ 0 ].length; 6 | 7 | const slope = ( right, down ) => 8 | { 9 | let trees = 0; 10 | 11 | for( let y = 0; y < input.length; y += down ) 12 | { 13 | const x = ( right * y / down ) % width; 14 | 15 | if( input[ y ][ x ] ) 16 | { 17 | trees++; 18 | } 19 | } 20 | 21 | return trees; 22 | }; 23 | 24 | const part1 = slope( 3, 1 ); 25 | const part2 = slope( 1, 1 ) * part1 * slope( 5, 1 ) * slope( 7, 1 ) * slope( 1, 2 ); 26 | 27 | return [ part1, part2 ]; 28 | }; 29 | -------------------------------------------------------------------------------- /2020/js/day4.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( '\n\n' ).map( parse ); 4 | 5 | function parse( document ) 6 | { 7 | return document 8 | .split( /\s/ ) 9 | .map( field => field.split( ':' ) ); 10 | } 11 | 12 | const eyeColors = new Set( [ 'amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth' ] ); 13 | const validators = 14 | { 15 | byr: value => value >= 1920 && value <= 2002, 16 | iyr: value => value >= 2010 && value <= 2020, 17 | eyr: value => value >= 2020 && value <= 2030, 18 | hcl: value => /^#[0-9a-f]{6}$/.test( value ), 19 | ecl: value => eyeColors.has( value ), 20 | pid: value => value.length === 9, 21 | cid: () => true, 22 | hgt: value => 23 | { 24 | value = value.match( /^(?[0-9]+)(?cm|in)$/ ); 25 | 26 | if( !value ) 27 | { 28 | return false; 29 | } 30 | 31 | switch( value.groups.unit ) 32 | { 33 | case 'cm': return value.groups.height >= 150 && value.groups.height <= 193; 34 | case 'in': return value.groups.height >= 59 && value.groups.height <= 76; 35 | } 36 | 37 | return false; 38 | }, 39 | }; 40 | 41 | let part1 = 0; 42 | let part2 = 0; 43 | 44 | for( const document of input ) 45 | { 46 | let fields = 0; 47 | let validationFailed = false; 48 | 49 | for( const [ key, value ] of document ) 50 | { 51 | if( key === 'cid' ) 52 | { 53 | continue; 54 | } 55 | 56 | fields++; 57 | 58 | if( !validators[ key ]( value ) ) 59 | { 60 | validationFailed = true; 61 | } 62 | } 63 | 64 | if( fields === 7 ) 65 | { 66 | part1++; 67 | 68 | if( !validationFailed ) 69 | { 70 | part2++; 71 | } 72 | } 73 | } 74 | 75 | return [ part1, part2 ]; 76 | }; 77 | -------------------------------------------------------------------------------- /2020/js/day5.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( pass => pass.replace( /./g, letter => 6 | { 7 | return letter === 'B' || letter === 'R' ? 1 : 0; 8 | } ) ) 9 | .map( pass => parseInt( pass, 2 ) ) 10 | .sort( ( a, b ) => b - a ); 11 | 12 | const part1 = input[ 0 ]; 13 | let part2 = 0; 14 | let lastPass = part1; 15 | 16 | for( const pass of input ) 17 | { 18 | if( lastPass - pass > 1 ) 19 | { 20 | part2 = pass + 1; 21 | break; 22 | } 23 | 24 | lastPass = pass; 25 | } 26 | 27 | return [ part1, part2 ]; 28 | }; 29 | -------------------------------------------------------------------------------- /2020/js/day6.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( '\n\n' ); 4 | 5 | const part1 = input 6 | .map( group => new Set( group.replace( /\n/g, '' ).split( '' ) ).size ) 7 | .reduce( ( a, b ) => a + b, 0 ); 8 | 9 | const part2 = input 10 | .map( group => 11 | { 12 | const people = group.split( '\n' ).map( l => l.split( '' ) ); 13 | const sum = new Map(); 14 | 15 | for( const answers of people ) 16 | { 17 | for( const answer of answers ) 18 | { 19 | sum.set( answer, 1 + ( sum.get( answer ) || 0 ) ); 20 | } 21 | } 22 | 23 | return [ ...sum.values() ].filter( a => a === people.length ).length; 24 | } ) 25 | .reduce( ( a, b ) => a + b, 0 ); 26 | 27 | return [ part1, part2 ]; 28 | }; 29 | -------------------------------------------------------------------------------- /2020/js/day7.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( x => x.match( /^(?[a-z]+ [a-z]+) bags contain (?.+)\./ ) ) 6 | .map( x => 7 | { 8 | const colors = new Map(); 9 | 10 | if( x.groups.contains !== 'no other bags' ) 11 | { 12 | const contains = x.groups.contains.matchAll( /(?[0-9]+) (?[a-z]+ [a-z]+) bag/g ); 13 | 14 | for( const color of contains ) 15 | { 16 | colors.set( color.groups.color, parseInt( color.groups.count, 10 ) ); 17 | } 18 | } 19 | 20 | return [ x.groups.color, colors ]; 21 | } ); 22 | 23 | input = new Map( input ); 24 | 25 | function containsShinyGoldBag( [ color, contains ] ) 26 | { 27 | if( typeof contains === 'number' ) 28 | { 29 | return containsShinyGoldBag( [ color, input.get( color ) ] ); 30 | } 31 | 32 | if( contains.has( 'shiny gold' ) ) 33 | { 34 | return true; 35 | } 36 | 37 | return [ ...contains ].some( containsShinyGoldBag ); 38 | } 39 | 40 | function countBags( [ color, contains ] ) 41 | { 42 | if( typeof contains === 'number' ) 43 | { 44 | return contains + countBags( [ color, input.get( color ) ] ) * contains; 45 | } 46 | 47 | return [ ...contains ].reduce( ( a, b ) => a + countBags( b ), 0 ); 48 | } 49 | 50 | const part1 = [ ...input ].reduce( ( a, b ) => a + containsShinyGoldBag( b ), 0 ); 51 | const part2 = countBags( [ null, input.get( 'shiny gold' ) ] ); 52 | 53 | return [ part1, part2 ]; 54 | }; 55 | -------------------------------------------------------------------------------- /2020/js/day8.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input 4 | .split( '\n' ) 5 | .map( x => 6 | { 7 | const instruction = x.match( /^(?[a-z]+) (?[-+][0-9]+)/ ).groups; 8 | instruction.num = parseInt( instruction.num, 10 ); 9 | instruction.seen = false; 10 | 11 | return instruction; 12 | } ); 13 | 14 | function run() 15 | { 16 | let cursor = 0; 17 | let accumulator = 0; 18 | 19 | while( cursor < input.length ) 20 | { 21 | const instruction = input[ cursor ]; 22 | 23 | if( instruction.seen ) 24 | { 25 | return { 26 | infiniteLoop: true, 27 | accumulator, 28 | }; 29 | } 30 | 31 | instruction.seen = true; 32 | 33 | switch( instruction.ins ) 34 | { 35 | case 'nop': cursor++; break; 36 | case 'acc': cursor++; accumulator += instruction.num; break; 37 | case 'jmp': cursor += instruction.num; break; 38 | } 39 | } 40 | 41 | return { 42 | infiniteLoop: false, 43 | accumulator, 44 | }; 45 | } 46 | 47 | const part1 = run().accumulator; 48 | let part2 = 0; 49 | 50 | outer: 51 | for( let i = input.length - 1; i >= 0; i-- ) 52 | { 53 | input.forEach( x => x.seen = false ); 54 | 55 | const originalInstruction = input[ i ].ins; 56 | 57 | switch( originalInstruction ) 58 | { 59 | case 'acc': continue outer; 60 | case 'nop': input[ i ].ins = 'jmp'; break; 61 | case 'jmp': input[ i ].ins = 'nop'; break; 62 | } 63 | 64 | const result = run(); 65 | 66 | if( !result.infiniteLoop ) 67 | { 68 | part2 = result.accumulator; 69 | break; 70 | } 71 | 72 | input[ i ].ins = originalInstruction; 73 | } 74 | 75 | return [ part1, part2 ]; 76 | }; 77 | -------------------------------------------------------------------------------- /2020/js/day9.js: -------------------------------------------------------------------------------- 1 | module.exports = ( input ) => 2 | { 3 | input = input.split( '\n' ).map( x => parseInt( x, 10 ) ); 4 | 5 | const PREAMBLE_SIZE = 25; 6 | let part1 = 0; 7 | 8 | outer: 9 | for( let i = PREAMBLE_SIZE; i < input.length; i++ ) 10 | { 11 | for( let j = i - PREAMBLE_SIZE; j < i; j++ ) 12 | { 13 | for( let y = i - PREAMBLE_SIZE; y < i; y++ ) 14 | { 15 | if( input[ j ] + input[ y ] === input[ i ] ) 16 | { 17 | continue outer; 18 | } 19 | } 20 | } 21 | 22 | part1 = input[ i ]; 23 | break; 24 | } 25 | 26 | let sum = 0; 27 | let lower = 0; 28 | let upper = 0; 29 | 30 | while( sum !== part1 || upper === lower ) 31 | { 32 | if( sum < part1 ) 33 | { 34 | upper++; 35 | sum += input[ upper ]; 36 | } 37 | 38 | if( sum > part1 ) 39 | { 40 | lower++; 41 | sum -= input[ lower ]; 42 | } 43 | } 44 | 45 | const slice = input.slice( lower + 1, upper + 1 ); 46 | const part2 = Math.min( ...slice ) + Math.max( ...slice ); 47 | 48 | return [ part1, part2 ]; 49 | }; 50 | -------------------------------------------------------------------------------- /2020/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "fix": "eslint --fix .", 4 | "test": "eslint . && ava" 5 | }, 6 | "devDependencies": { 7 | "ava": "^3.13.0", 8 | "eslint": "^7.11.0" 9 | }, 10 | "ava": { 11 | "files": [ 12 | "test.js" 13 | ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2020/test.js: -------------------------------------------------------------------------------- 1 | const test = require( 'ava' ); 2 | const { readFileSync } = require( 'fs' ); 3 | 4 | process.chdir( __dirname ); 5 | 6 | test( '2020', t => 7 | { 8 | assert( t, 1, 63616, 67877784 ); 9 | assert( t, 2, 439, 584 ); 10 | assert( t, 3, 276, 7812180000 ); 11 | assert( t, 4, 208, 167 ); 12 | assert( t, 5, 901, 661 ); 13 | assert( t, 6, 6565, 3137 ); 14 | assert( t, 7, 169, 82372 ); 15 | assert( t, 8, 2003, 1984 ); 16 | assert( t, 9, 556543474, 76096372 ); 17 | assert( t, 10, 2760, 13816758796288 ); 18 | assert( t, 11, 2296, 2089 ); 19 | assert( t, 12, 845, 27016 ); 20 | assert( t, 13, 138, 226845233210288 ); 21 | assert( t, 14, 18630548206046, 4254673508445 ); 22 | assert( t, 15, 1194, 48710 ); 23 | assert( t, 16, 20231, 1940065747861 ); 24 | assert( t, 17, 223, 1884 ); 25 | assert( t, 18, 9535936849815, 472171581333710 ); 26 | assert( t, 19, 248, 381 ); 27 | assert( t, 21, 2485, 'bqkndvb,zmb,bmrmhm,snhrpv,vflms,bqtvr,qzkjrtl,rkkrx' ); 28 | assert( t, 22, 33400, 33745 ); 29 | assert( t, 23, 78569234, 565615814504 ); 30 | assert( t, 24, 488, 4118 ); 31 | assert( t, 25, 7269858, 0 ); 32 | } ); 33 | 34 | function assert( t, day, answer1, answer2 ) 35 | { 36 | let input = readFileSync( `./data/day${day}.txt` ).toString(); 37 | input = input.replace( /\r/g, '' ).trim(); 38 | 39 | const solution = require( `./js/day${day}.js` ); 40 | const result = solution( input ); 41 | 42 | t.is( result[ 0 ], answer1 ); 43 | t.is( result[ 1 ], answer2 ); 44 | } 45 | -------------------------------------------------------------------------------- /2021/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": ".NET Core Launch (console)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build", 9 | "program": "${workspaceFolder}/Answers/bin/Debug/net6.0/2021.dll", 10 | "args": [], 11 | "cwd": "${workspaceFolder}/Answers", 12 | "console": "internalConsole", 13 | "stopAtEntry": false 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /2021/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/Answers/2021.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/Answers/2021.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "${workspaceFolder}/Answers/2021.csproj", 36 | "/property:GenerateFullPaths=true", 37 | "/consoleloggerparameters:NoSummary" 38 | ], 39 | "problemMatcher": "$msCompile" 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /2021/2021.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30114.105 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "2021", "Answers\2021.csproj", "{D9537297-BC8C-4803-B23A-6D4FD42B2B95}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{86C4B728-1413-41FF-AA75-A678770209A1}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(SolutionProperties) = preSolution 16 | HideSolutionNode = FALSE 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Release|Any CPU.Build.0 = Release|Any CPU 23 | {86C4B728-1413-41FF-AA75-A678770209A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {86C4B728-1413-41FF-AA75-A678770209A1}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {86C4B728-1413-41FF-AA75-A678770209A1}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {86C4B728-1413-41FF-AA75-A678770209A1}.Release|Any CPU.Build.0 = Release|Any CPU 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /2021/Answers/2021.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net6.0 5 | AdventOfCode2021 6 | enable 7 | true 8 | CA1822 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /2021/Answers/AnswerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode2021; 4 | 5 | [AttributeUsage(AttributeTargets.Class)] 6 | class AnswerAttribute : Attribute 7 | { 8 | public int Day { get; init; } 9 | public bool Slow { get; init; } 10 | public AnswerAttribute(int day) => Day = day; 11 | public AnswerAttribute(int day, bool slow) 12 | { 13 | Day = day; 14 | Slow = slow; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /2021/Answers/IAnswer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode2021; 4 | 5 | interface IAnswer 6 | { 7 | public (string Part1, string Part2) Solve(string input); 8 | } 9 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode2021; 4 | 5 | [Answer(1)] 6 | class Day1 : IAnswer 7 | { 8 | public (string Part1, string Part2) Solve(string input) 9 | { 10 | var lines = input.Split('\n'); 11 | var numbers = Array.ConvertAll(lines, int.Parse); 12 | var part1 = 0; 13 | var part2 = 0; 14 | 15 | for (var i = 1; i < numbers.Length; i++) 16 | { 17 | var number = numbers[i]; 18 | 19 | if (number > numbers[i - 1]) 20 | { 21 | part1++; 22 | } 23 | 24 | if (i > 2 && number > numbers[i - 3]) 25 | { 26 | part2++; 27 | } 28 | } 29 | 30 | return (part1.ToString(), part2.ToString()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day12.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace AdventOfCode2021; 5 | 6 | [Answer(12, slow: true)] 7 | class Day12 : IAnswer 8 | { 9 | const string START = "start"; 10 | const string END = "end"; 11 | 12 | readonly Dictionary> Caves = new(); 13 | 14 | public (string Part1, string Part2) Solve(string input) 15 | { 16 | foreach (var line in input.Split('\n')) 17 | { 18 | var path = line.Split('-', 2); 19 | 20 | if (!Caves.ContainsKey(path[0])) 21 | { 22 | Caves.Add(path[0], new List()); 23 | } 24 | 25 | if (!Caves.ContainsKey(path[1])) 26 | { 27 | Caves.Add(path[1], new List()); 28 | } 29 | 30 | Caves[path[0]].Add(path[1]); 31 | Caves[path[1]].Add(path[0]); 32 | } 33 | 34 | var part1 = Score(START, new Stack(), true); 35 | var part2 = Score(START, new Stack(), false); 36 | 37 | return (part1.ToString(), part2.ToString()); 38 | } 39 | 40 | int Score(string start, Stack visited, bool moreThanOnce) 41 | { 42 | if (start == END) 43 | { 44 | return 1; 45 | } 46 | 47 | var isSmall = start.All(char.IsLower); 48 | 49 | if (isSmall) 50 | { 51 | visited.Push(start); 52 | } 53 | 54 | var score = 0; 55 | 56 | foreach (var point in Caves[start]) 57 | { 58 | var newMoreThanOnce = moreThanOnce; 59 | if (visited.Contains(point)) 60 | { 61 | if (moreThanOnce || point == START) 62 | { 63 | continue; 64 | } 65 | 66 | newMoreThanOnce = true; 67 | } 68 | 69 | score += Score(point, visited, newMoreThanOnce); 70 | } 71 | 72 | if (isSmall) 73 | { 74 | visited.Pop(); 75 | } 76 | 77 | return score; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day13.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | 5 | namespace AdventOfCode2021; 6 | 7 | [Answer(13)] 8 | class Day13 : IAnswer 9 | { 10 | public (string Part1, string Part2) Solve(string input) 11 | { 12 | var inputs = input.Split("\n\n"); 13 | var numbers = inputs[0] 14 | .Split('\n') 15 | .Select(l => l 16 | .Split(',', 2) 17 | .Select(n => int.Parse(n)) 18 | .ToArray() 19 | ) 20 | .ToArray(); 21 | 22 | var maxX = 0; 23 | var maxY = 0; 24 | var part1 = 0; 25 | 26 | foreach (var line in inputs[1].Split('\n')) 27 | { 28 | var fold = int.Parse(line[13..]); 29 | var isY = line[11] == 'y'; 30 | 31 | if (isY) 32 | { 33 | foreach (var number in numbers) 34 | { 35 | var y = number[1]; 36 | if (y > fold) 37 | { 38 | number[1] = 2 * fold - y; 39 | } 40 | } 41 | 42 | maxY = fold; 43 | } 44 | else 45 | { 46 | foreach (var number in numbers) 47 | { 48 | var x = number[0]; 49 | if (x > fold) 50 | { 51 | number[0] = 2 * fold - x; 52 | } 53 | } 54 | 55 | maxX = fold; 56 | } 57 | 58 | if (part1 == 0) 59 | { 60 | part1 = numbers.DistinctBy(x => x[1] * 10000 + x[0]).Count(); 61 | } 62 | } 63 | 64 | var grid = new bool[maxY * maxX + maxX]; 65 | 66 | foreach (var coord in numbers) 67 | { 68 | grid[coord[1] * maxX + coord[0]] = true; 69 | } 70 | 71 | var part2 = new StringBuilder(maxY * maxX + maxY + 1); 72 | part2.Append('\n'); 73 | 74 | for (int y = 0; y < maxY; y++) 75 | { 76 | for (int x = 0; x < maxX; x++) 77 | { 78 | part2.Append(grid[y * maxX + x] ? '#' : ' '); 79 | } 80 | 81 | part2.Append('\n'); 82 | } 83 | 84 | return (part1.ToString(), part2.ToString()); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day14.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace AdventOfCode2021; 6 | 7 | [Answer(14)] 8 | class Day14 : IAnswer 9 | { 10 | public (string Part1, string Part2) Solve(string input) 11 | { 12 | const int HASH_SIZE = 10000; 13 | var hash = static (int a, int b) => a * HASH_SIZE + b; 14 | var lines = input.Split('\n'); 15 | var polymer = lines[0].ToArray(); 16 | var insertions = lines 17 | .Skip(2) 18 | .Select(l => l 19 | .Split(" -> ") 20 | .ToArray() 21 | ) 22 | .ToDictionary(x => hash(x[0][0], x[0][1]), y => y[1][0]); 23 | 24 | var pairs = new Dictionary(); 25 | var chars = new Dictionary(); 26 | long part1 = 0; 27 | 28 | for (var i = 0; i < polymer.Length; i++) 29 | { 30 | chars[polymer[i]] = chars.GetValueOrDefault(polymer[i]) + 1; 31 | 32 | if (i < polymer.Length - 1) 33 | { 34 | var pair = hash(polymer[i], polymer[i + 1]); 35 | pairs[pair] = pairs.GetValueOrDefault(pair) + 1; 36 | } 37 | } 38 | 39 | for (var step = 0; step < 40; step++) 40 | { 41 | var copy = new Dictionary(pairs); 42 | 43 | foreach (var pair in copy) 44 | { 45 | var insert = insertions[pair.Key]; 46 | pairs[pair.Key] -= pair.Value; 47 | 48 | var newPair = hash(pair.Key / HASH_SIZE, insert); 49 | pairs[newPair] = pairs.GetValueOrDefault(newPair) + pair.Value; 50 | 51 | newPair = hash(insert, pair.Key % HASH_SIZE); 52 | pairs[newPair] = pairs.GetValueOrDefault(newPair) + pair.Value; 53 | chars[insert] = chars.GetValueOrDefault(insert) + pair.Value; 54 | } 55 | 56 | if (step == 9) 57 | { 58 | part1 = chars.Values.Max() - chars.Values.Min(); 59 | } 60 | } 61 | 62 | var part2 = chars.Values.Max() - chars.Values.Min(); 63 | 64 | return (part1.ToString(), part2.ToString()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day17.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AdventOfCode2021; 5 | 6 | [Answer(17)] 7 | class Day17 : IAnswer 8 | { 9 | public (string Part1, string Part2) Solve(string input) 10 | { 11 | var split = input.Split(new char[] { 12 | '.', 13 | '=', 14 | ',', 15 | }); 16 | var x1 = int.Parse(split[1]); 17 | var x2 = int.Parse(split[3]); 18 | var y1 = int.Parse(split[5]); 19 | var y2 = int.Parse(split[7]); 20 | 21 | var part1 = y1 * (y1 + 1) / 2; 22 | var part2 = 0; 23 | var yMin = Math.Min(y1, y2); 24 | var yMax = Math.Abs(yMin); 25 | var xMin = ((int)Math.Sqrt(8 * x1 + 1) - 1) / 2; 26 | 27 | for (var x = xMin; x <= x2; x++) 28 | { 29 | if (x > x2 / 2 && x < x1) 30 | { 31 | continue; 32 | } 33 | 34 | for (var y = yMin; y <= yMax; y++) 35 | { 36 | var coordinates = (x: 0, y: 0); 37 | var velocity = (x, y); 38 | 39 | while (true) 40 | { 41 | coordinates.x += velocity.x; 42 | coordinates.y += velocity.y; 43 | 44 | if (coordinates.x > x2 || coordinates.y < yMin) 45 | { 46 | break; 47 | } 48 | 49 | if (coordinates.x >= x1 && coordinates.x <= x2 && coordinates.y >= y1 && coordinates.y <= y2) 50 | { 51 | part2++; 52 | break; 53 | } 54 | 55 | if (velocity.x > 0) 56 | { 57 | if (--velocity.x == 0 && coordinates.x < x1) 58 | { 59 | break; 60 | } 61 | } 62 | 63 | velocity.y--; 64 | } 65 | } 66 | } 67 | 68 | return (part1.ToString(), part2.ToString()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace AdventOfCode2021; 5 | 6 | [Answer(2)] 7 | class Day2 : IAnswer 8 | { 9 | enum Direction 10 | { 11 | Forward, 12 | Up, 13 | Down, 14 | } 15 | 16 | public (string Part1, string Part2) Solve(string input) 17 | { 18 | var lines = input 19 | .Split('\n') 20 | .Select(l => 21 | { 22 | var sp = l.Split(' ', 2); 23 | var dir = sp[0] switch 24 | { 25 | "forward" => Direction.Forward, 26 | "up" => Direction.Up, 27 | "down" => Direction.Down, 28 | _ => throw new NotImplementedException(), 29 | }; 30 | 31 | return (Direction: dir, Units: int.Parse(sp[1])); 32 | }); 33 | 34 | var horizontal = 0; 35 | var depth = 0; // part 2 36 | var aim = 0; 37 | 38 | foreach (var (direction, units) in lines) 39 | { 40 | switch (direction) 41 | { 42 | case Direction.Forward: 43 | horizontal += units; 44 | depth += units * aim; 45 | break; 46 | case Direction.Up: aim -= units; break; 47 | case Direction.Down: aim += units; break; 48 | } 49 | } 50 | 51 | var part1 = horizontal * aim; 52 | var part2 = horizontal * depth; 53 | 54 | return (part1.ToString(), part2.ToString()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day23.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode2021; 2 | 3 | [Answer(23)] 4 | class Day23 : IAnswer 5 | { 6 | public (string Part1, string Part2) Solve(string input) 7 | { 8 | var part1 = 0; 9 | var part2 = 0; 10 | return (part1.ToString(), part2.ToString()); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day5.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace AdventOfCode2021; 6 | 7 | [Answer(5)] 8 | class Day5 : IAnswer 9 | { 10 | record Coordinate(int X, int Y); 11 | 12 | public (string Part1, string Part2) Solve(string input) 13 | { 14 | var lines = input 15 | .Split('\n') 16 | .Select(l => l 17 | .Split(" -> ") 18 | .Select(n => 19 | { 20 | var i = n 21 | .Split(',') 22 | .Select(x => int.Parse(x)) 23 | .ToArray(); 24 | 25 | return new Coordinate(i[0], i[1]); 26 | } 27 | ) 28 | .ToList() 29 | ) 30 | .ToList(); 31 | 32 | var maxX = 1 + lines.Max(x => x.Max(x => x.X)); 33 | var maxY = 1 + lines.Max(y => y.Max(y => y.Y)); 34 | var grid = new byte[maxX * maxY]; 35 | var part1 = CalculateGrid(grid, maxX, lines, false); 36 | var part2 = CalculateGrid(grid, maxX, lines, true); 37 | 38 | return (part1.ToString(), part2.ToString()); 39 | } 40 | 41 | int CalculateGrid(byte[] grid, int stride, List> lines, bool allowDiagonals = false) 42 | { 43 | foreach (var coords in lines) 44 | { 45 | var start = coords[0]; 46 | var end = coords[1]; 47 | var lenX = end.X - start.X; 48 | var lenY = end.Y - start.Y; 49 | var dX = Math.Sign(lenX); 50 | var dY = Math.Sign(lenY); 51 | 52 | if ((dX == 0 || dY == 0) == allowDiagonals) 53 | { 54 | continue; 55 | } 56 | 57 | var length = dY == 0 ? Math.Abs(lenX) : Math.Abs(lenY); 58 | 59 | for (var i = 0; i <= length; i++) 60 | { 61 | var x = start.X + i * dX; 62 | var y = start.Y + i * dY; 63 | grid[y * stride + x]++; 64 | } 65 | } 66 | 67 | var result = 0; 68 | 69 | foreach (var value in grid) 70 | { 71 | if (value > 1) 72 | { 73 | result++; 74 | } 75 | } 76 | 77 | return result; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day6.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace AdventOfCode2021; 5 | 6 | [Answer(6)] 7 | class Day6 : IAnswer 8 | { 9 | public (string Part1, string Part2) Solve(string input) 10 | { 11 | var timers = new long[9]; 12 | 13 | for (var i = input.Length - 1; i >= 0; i -= 2) 14 | { 15 | timers[input[i] - '0']++; 16 | } 17 | 18 | for (var day = 1; day <= 80; day++) Update(timers); 19 | var part1 = timers.Sum(); 20 | 21 | for (var day = 81; day <= 256; day++) Update(timers); 22 | var part2 = timers.Sum(); 23 | 24 | return (part1.ToString(), part2.ToString()); 25 | } 26 | 27 | private void Update(long[] timers) 28 | { 29 | var newFish = timers[0]; 30 | 31 | for (var timer = 0; timer < 8; timer++) 32 | { 33 | timers[timer] = timers[timer + 1]; 34 | } 35 | 36 | timers[8] = newFish; 37 | timers[6] += newFish; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /2021/Answers/Solutions/Day7.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace AdventOfCode2021; 5 | 6 | [Answer(7)] 7 | class Day7 : IAnswer 8 | { 9 | public (string Part1, string Part2) Solve(string input) 10 | { 11 | var numbers = Array.ConvertAll(input.Split(','), int.Parse); 12 | var max = numbers.Max(); 13 | 14 | Array.Sort(numbers); 15 | 16 | var part1 = 0; 17 | var median = numbers[numbers.Length / 2]; 18 | 19 | for (var i = 0; i < numbers.Length; i++) 20 | { 21 | part1 += Math.Abs(numbers[i] - median); 22 | } 23 | 24 | var part2 = BinarySearch(numbers, 0, max, (numbers, position) => 25 | { 26 | var fuel = 0; 27 | 28 | for (var i = numbers.Length - 1; i >= 0; i--) 29 | { 30 | var diff = Math.Abs(numbers[i] - position); 31 | fuel += diff * (diff + 1) / 2; 32 | } 33 | 34 | return fuel; 35 | }); 36 | 37 | return (part1.ToString(), part2.ToString()); 38 | } 39 | 40 | private int BinarySearch(int[] numbers, int from, int to, Func function) 41 | { 42 | if (from == to) 43 | { 44 | return function(numbers, from); 45 | } 46 | 47 | var median = (from + to) / 2; 48 | 49 | if (function(numbers, median) < function(numbers, median + 1)) 50 | { 51 | return BinarySearch(numbers, from, median, function); 52 | } 53 | else 54 | { 55 | return BinarySearch(numbers, median + 1, to, function); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /2021/DataExamples/answers.txt: -------------------------------------------------------------------------------- 1 | 7 | 5 2 | 150 | 900 3 | 198 | 230 4 | 4512 | 1924 5 | 5 | 12 6 | 5934 | 26984457539 7 | 37 | 168 8 | 26 | 61229 9 | 15 | 1134 10 | 26397 | 288957 11 | 1656 | 195 12 | 226 | 3509 13 | 17 | \n#####\n# #\n# #\n# #\n#####\n \n \n 14 | 1588 | 2188189693529 15 | 40 | 315 16 | 20 | 1 17 | 45 | 112 18 | 4140 | 3993 19 | 79 | 3621 20 | 35 | 3351 21 | 739785 | 444356092776315 22 | 474140 | 2758514936282235 23 | 12521 | 44169 24 | 96299896449997 | 31162141116841 25 | 58 | 0 26 | -------------------------------------------------------------------------------- /2021/DataExamples/day1.txt: -------------------------------------------------------------------------------- 1 | 199 2 | 200 3 | 208 4 | 210 5 | 200 6 | 207 7 | 240 8 | 269 9 | 260 10 | 263 11 | -------------------------------------------------------------------------------- /2021/DataExamples/day10.txt: -------------------------------------------------------------------------------- 1 | [({(<(())[]>[[{[]{<()<>> 2 | [(()[<>])]({[<{<<[]>>( 3 | {([(<{}[<>[]}>{[]{[(<()> 4 | (((({<>}<{<{<>}{[]{[]{} 5 | [[<[([]))<([[{}[[()]]] 6 | [{[{({}]{}}([{[{{{}}([] 7 | {<[[]]>}<{[{[{[]{()[[[] 8 | [<(<(<(<{}))><([]([]() 9 | <{([([[(<>()){}]>(<<{{ 10 | <{([{{}}[<[[[<>{}]]]>[]] 11 | -------------------------------------------------------------------------------- /2021/DataExamples/day11.txt: -------------------------------------------------------------------------------- 1 | 5483143223 2 | 2745854711 3 | 5264556173 4 | 6141336146 5 | 6357385478 6 | 4167524645 7 | 2176841721 8 | 6882881134 9 | 4846848554 10 | 5283751526 11 | -------------------------------------------------------------------------------- /2021/DataExamples/day12.txt: -------------------------------------------------------------------------------- 1 | fs-end 2 | he-DX 3 | fs-he 4 | start-DX 5 | pj-DX 6 | end-zg 7 | zg-sl 8 | zg-pj 9 | pj-he 10 | RW-he 11 | fs-DX 12 | pj-RW 13 | zg-RW 14 | start-pj 15 | he-WI 16 | zg-he 17 | pj-fs 18 | start-RW 19 | -------------------------------------------------------------------------------- /2021/DataExamples/day13.txt: -------------------------------------------------------------------------------- 1 | 6,10 2 | 0,14 3 | 9,10 4 | 0,3 5 | 10,4 6 | 4,11 7 | 6,0 8 | 6,12 9 | 4,1 10 | 0,13 11 | 10,12 12 | 3,4 13 | 3,0 14 | 8,4 15 | 1,10 16 | 2,14 17 | 8,10 18 | 9,0 19 | 20 | fold along y=7 21 | fold along x=5 22 | -------------------------------------------------------------------------------- /2021/DataExamples/day14.txt: -------------------------------------------------------------------------------- 1 | NNCB 2 | 3 | CH -> B 4 | HH -> N 5 | CB -> H 6 | NH -> C 7 | HB -> C 8 | HC -> B 9 | HN -> C 10 | NN -> C 11 | BH -> H 12 | NC -> B 13 | NB -> B 14 | BN -> B 15 | BB -> N 16 | BC -> B 17 | CC -> N 18 | CN -> C 19 | -------------------------------------------------------------------------------- /2021/DataExamples/day15.txt: -------------------------------------------------------------------------------- 1 | 1163751742 2 | 1381373672 3 | 2136511328 4 | 3694931569 5 | 7463417111 6 | 1319128137 7 | 1359912421 8 | 3125421639 9 | 1293138521 10 | 2311944581 11 | -------------------------------------------------------------------------------- /2021/DataExamples/day16.txt: -------------------------------------------------------------------------------- 1 | 9C0141080250320F1802104A08 2 | -------------------------------------------------------------------------------- /2021/DataExamples/day17.txt: -------------------------------------------------------------------------------- 1 | target area: x=20..30, y=-10..-5 2 | -------------------------------------------------------------------------------- /2021/DataExamples/day18.txt: -------------------------------------------------------------------------------- 1 | [[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]] 2 | [[[5,[2,8]],4],[5,[[9,9],0]]] 3 | [6,[[[6,2],[5,6]],[[7,6],[4,7]]]] 4 | [[[6,[0,7]],[0,9]],[4,[9,[9,0]]]] 5 | [[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]] 6 | [[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]] 7 | [[[[5,4],[7,7]],8],[[8,3],8]] 8 | [[9,3],[[9,9],[6,[4,9]]]] 9 | [[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]] 10 | [[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]] 11 | -------------------------------------------------------------------------------- /2021/DataExamples/day2.txt: -------------------------------------------------------------------------------- 1 | forward 5 2 | down 5 3 | forward 8 4 | up 3 5 | down 8 6 | forward 2 7 | -------------------------------------------------------------------------------- /2021/DataExamples/day20.txt: -------------------------------------------------------------------------------- 1 | ..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..# 2 | 3 | #..#. 4 | #.... 5 | ##..# 6 | ..#.. 7 | ..### 8 | -------------------------------------------------------------------------------- /2021/DataExamples/day21.txt: -------------------------------------------------------------------------------- 1 | Player 1 starting position: 4 2 | Player 2 starting position: 8 3 | -------------------------------------------------------------------------------- /2021/DataExamples/day23.txt: -------------------------------------------------------------------------------- 1 | ############# 2 | #...........# 3 | ###B#C#B#D### 4 | #A#D#C#A# 5 | ######### 6 | -------------------------------------------------------------------------------- /2021/DataExamples/day25.txt: -------------------------------------------------------------------------------- 1 | v...>>.vv> 2 | .vv>>.vv.. 3 | >>.>v>...v 4 | >>v>>.>.v. 5 | v>v.vv.v.. 6 | >.>>..v... 7 | .vv..>.>v. 8 | v.v..>>v.v 9 | ....v..v.> 10 | -------------------------------------------------------------------------------- /2021/DataExamples/day3.txt: -------------------------------------------------------------------------------- 1 | 00100 2 | 11110 3 | 10110 4 | 10111 5 | 10101 6 | 01111 7 | 00111 8 | 11100 9 | 10000 10 | 11001 11 | 00010 12 | 01010 13 | -------------------------------------------------------------------------------- /2021/DataExamples/day4.txt: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | 22 13 17 11 0 4 | 8 2 23 4 24 5 | 21 9 14 16 7 6 | 6 10 3 18 5 7 | 1 12 20 15 19 8 | 9 | 3 15 0 2 22 10 | 9 18 13 17 5 11 | 19 8 7 25 23 12 | 20 11 10 24 4 13 | 14 21 16 12 6 14 | 15 | 14 21 17 24 4 16 | 10 16 15 9 19 17 | 18 8 23 26 20 18 | 22 11 13 6 5 19 | 2 0 12 3 7 20 | -------------------------------------------------------------------------------- /2021/DataExamples/day5.txt: -------------------------------------------------------------------------------- 1 | 0,9 -> 5,9 2 | 8,0 -> 0,8 3 | 9,4 -> 3,4 4 | 2,2 -> 2,1 5 | 7,0 -> 7,4 6 | 6,4 -> 2,0 7 | 0,9 -> 2,9 8 | 3,4 -> 1,4 9 | 0,0 -> 8,8 10 | 5,5 -> 8,2 11 | -------------------------------------------------------------------------------- /2021/DataExamples/day6.txt: -------------------------------------------------------------------------------- 1 | 3,4,3,1,2 2 | -------------------------------------------------------------------------------- /2021/DataExamples/day7.txt: -------------------------------------------------------------------------------- 1 | 16,1,2,0,4,2,7,1,2,14 2 | -------------------------------------------------------------------------------- /2021/DataExamples/day8.txt: -------------------------------------------------------------------------------- 1 | be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe 2 | edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc 3 | fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg 4 | fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb 5 | aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea 6 | fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb 7 | dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe 8 | bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef 9 | egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb 10 | gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce 11 | -------------------------------------------------------------------------------- /2021/DataExamples/day9.txt: -------------------------------------------------------------------------------- 1 | 2199943210 2 | 3987894921 3 | 9856789892 4 | 8767896789 5 | 9899965678 6 | -------------------------------------------------------------------------------- /2021/Tests/Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | enable 5 | false 6 | true 7 | 8 | 9 | 10 | 11 | 12 | runtime; build; native; contentfiles; analyzers; buildtransitive 13 | all 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /2021/prep.ps1: -------------------------------------------------------------------------------- 1 | $Day = (Get-Date).Day 2 | 3 | New-Item -Path "Data" -Name "day$Day.txt" -ItemType "file" 4 | New-Item -Path "DataExamples" -Name "day$Day.txt" -ItemType "file" 5 | 6 | $Path = "Answers\Solutions\Day$Day.cs" 7 | 8 | if ((Test-Path $Path) -eq $False) { 9 | ((Get-Content "Answers\Solutions\Day1.cs" -Raw) -replace [regex]::escape("[Answer(1)]"),"[Answer($Day)]" -replace "class Day1","class Day$Day") | Set-Content -Path $Path 10 | } 11 | -------------------------------------------------------------------------------- /2022/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": ".NET Core Launch (console)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build", 9 | "program": "${workspaceFolder}/Answers/bin/Debug/net7.0/win-x64/AdventOfCode.dll", 10 | "args": [], 11 | "cwd": "${workspaceFolder}/Answers", 12 | "console": "internalConsole", 13 | "stopAtEntry": false 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /2022/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/Answers/AdventOfCode.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/Answers/AdventOfCode.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "${workspaceFolder}/Answers/AdventOfCode.csproj", 36 | "/property:GenerateFullPaths=true", 37 | "/consoleloggerparameters:NoSummary" 38 | ], 39 | "problemMatcher": "$msCompile" 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /2022/Answers/AdventOfCode.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net7.0 5 | AdventOfCode 6 | enable 7 | false 8 | CA1822 9 | true 10 | true 11 | true 12 | true 13 | $(DefineConstants);NO_BENCHMARK 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /2022/Answers/AnswerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode; 4 | 5 | [AttributeUsage(AttributeTargets.Class)] 6 | class AnswerAttribute : Attribute 7 | { 8 | public int Day { get; init; } 9 | public bool Slow { get; init; } 10 | public AnswerAttribute(int day) => Day = day; 11 | public AnswerAttribute(int day, bool slow) 12 | { 13 | Day = day; 14 | Slow = slow; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /2022/Answers/BenchmarkSolver.cs: -------------------------------------------------------------------------------- 1 | #if !NO_BENCHMARK 2 | using System.Threading.Tasks; 3 | using BenchmarkDotNet.Attributes; 4 | 5 | namespace AdventOfCode; 6 | 7 | [MemoryDiagnoser] 8 | public class BenchmarkSolver 9 | { 10 | [Params(15)] 11 | public int Day { get; set; } 12 | 13 | private string Data = string.Empty; 14 | 15 | [GlobalSetup] 16 | public async Task Setup() 17 | { 18 | //Day = System.DateTime.Today.Day; 19 | Data = await Solver.LoadData(Day); 20 | } 21 | 22 | [Benchmark] 23 | public (string Part1, string Part2) Solve() 24 | { 25 | return Solver.Solve(Day, Data); 26 | } 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /2022/Answers/IAnswer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode; 4 | 5 | public interface IAnswer 6 | { 7 | public (string Part1, string Part2) Solve(string input); 8 | } 9 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day0.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode; 2 | 3 | [Answer(0)] 4 | public class Day0 : IAnswer 5 | { 6 | public (string Part1, string Part2) Solve(string input) 7 | { 8 | var part1 = 0; 9 | var part2 = 0; 10 | 11 | return (part1.ToString(), part2.ToString()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day1.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode; 2 | 3 | [Answer(1)] 4 | public class Day1 : IAnswer 5 | { 6 | public (string Part1, string Part2) Solve(string input) 7 | { 8 | var length = input.Length; 9 | var current = 0; 10 | var num = 0; 11 | var a = 0; 12 | var b = 0; 13 | var c = 0; 14 | 15 | void Swap(int x) 16 | { 17 | if (a < x) 18 | { 19 | c = b; 20 | b = a; 21 | a = x; 22 | } 23 | else if (b < x) 24 | { 25 | c = b; 26 | b = x; 27 | } 28 | else if (c < x) 29 | { 30 | c = x; 31 | } 32 | } 33 | 34 | for (var i = 0; i < length; i++) 35 | { 36 | if (input[i] == '\n') 37 | { 38 | if (num > 0) 39 | { 40 | current += num; 41 | num = 0; 42 | } 43 | else 44 | { 45 | Swap(current); 46 | current = 0; 47 | } 48 | } 49 | else 50 | { 51 | num = 10 * num + input[i] - '0'; 52 | } 53 | } 54 | 55 | Swap(current + num); 56 | 57 | var part1 = a; 58 | var part2 = a + b + c; 59 | 60 | return (part1.ToString(), part2.ToString()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day10.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(10)] 7 | public class Day10 : IAnswer 8 | { 9 | public (string Part1, string Part2) Solve(string input) 10 | { 11 | const int WIDTH = 40; 12 | const int HEIGHT = 6; 13 | 14 | var X = 1; 15 | var cycle = 0; 16 | var part1 = 0; 17 | var part2 = new StringBuilder(WIDTH * HEIGHT + HEIGHT + 1); 18 | part2.Append('\n'); 19 | 20 | void CheckCycle() 21 | { 22 | var stride = cycle % WIDTH; 23 | 24 | if (stride == X - 1 || stride == X || stride == X + 1) 25 | { 26 | part2.Append('#'); 27 | } 28 | else 29 | { 30 | part2.Append('.'); 31 | } 32 | 33 | if (stride == WIDTH - 1) 34 | { 35 | part2.Append('\n'); 36 | } 37 | 38 | cycle++; 39 | 40 | if ((cycle + 20) % 40 == 0) 41 | { 42 | part1 += X * cycle; 43 | } 44 | } 45 | 46 | foreach (var line in input.AsSpan().EnumerateLines()) 47 | { 48 | CheckCycle(); 49 | 50 | if (line[0] == 'a') 51 | { 52 | CheckCycle(); 53 | X += int.Parse(line[5..]); 54 | } 55 | } 56 | 57 | return (part1.ToString(), part2.ToString()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day2.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode; 2 | 3 | [Answer(2)] 4 | public class Day2 : IAnswer 5 | { 6 | public (string Part1, string Part2) Solve(string input) 7 | { 8 | var part1 = 0; 9 | var part2 = 0; 10 | 11 | static int Score(int a, int b) 12 | { 13 | var result = (3 + b - a) % 3; 14 | return b switch 15 | { 16 | 2 => 1, 17 | 1 => 2, 18 | 0 => 3, 19 | _ => throw new System.NotImplementedException(), 20 | } + result switch 21 | { 22 | 0 => 3, 23 | 1 => 0, 24 | 2 => 6, 25 | _ => throw new System.NotImplementedException(), 26 | }; 27 | }; 28 | 29 | for (var i = 0; i < input.Length; i += 4) 30 | { 31 | var a = 'C' - input[i]; 32 | var b = 'Z' - input[i + 2]; 33 | 34 | part1 += Score(a, b); 35 | 36 | b = input[i + 2] switch 37 | { 38 | 'X' => (a + 1) % 3, 39 | 'Y' => a, 40 | 'Z' => (((a - 1) % 3) + 3) % 3, 41 | _ => throw new System.NotImplementedException(), 42 | }; 43 | 44 | part2 += Score(a, b); 45 | } 46 | 47 | return (part1.ToString(), part2.ToString()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day25.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace AdventOfCode; 6 | 7 | [Answer(25)] 8 | public class Day25 : IAnswer 9 | { 10 | public (string Part1, string Part2) Solve(string input) 11 | { 12 | static long ParseSnafu(ReadOnlySpan line) 13 | { 14 | var result = 0L; 15 | 16 | foreach (var c in line) 17 | { 18 | result = 5L * result + c switch 19 | { 20 | '2' => 2, 21 | '1' => 1, 22 | '0' => 0, 23 | '-' => -1, 24 | '=' => -2, 25 | _ => throw new NotImplementedException(), 26 | }; 27 | } 28 | 29 | return result; 30 | } 31 | 32 | static string EncodeSnafu(long number) 33 | { 34 | var chars = new List(20); 35 | 36 | while (number > 0) 37 | { 38 | (number, var remainder) = Math.DivRem(number, 5); 39 | 40 | chars.Add(remainder switch 41 | { 42 | 0 => '0', 43 | 2 => '2', 44 | 1 => '1', 45 | 3 => '=', 46 | 4 => '-', 47 | _ => throw new NotImplementedException(), 48 | }); 49 | 50 | if (remainder > 2) 51 | { 52 | number++; 53 | } 54 | } 55 | 56 | var str = new StringBuilder(chars.Count); 57 | 58 | for (var i = chars.Count - 1; i >= 0; i--) 59 | { 60 | str.Append(chars[i]); 61 | } 62 | 63 | return str.ToString(); 64 | } 65 | 66 | var sum = 0L; 67 | 68 | foreach (var line in input.AsSpan().EnumerateLines()) 69 | { 70 | sum += ParseSnafu(line); 71 | } 72 | 73 | return (EncodeSnafu(sum), "Woo!"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(3)] 7 | public class Day3 : IAnswer 8 | { 9 | public (string Part1, string Part2) Solve(string input) 10 | { 11 | var span = input.AsSpan(); 12 | 13 | var part1 = 0; 14 | var part2 = 0; 15 | var line = 0; 16 | var hasMore = true; 17 | ReadOnlySpan prev1 = span[0..1]; 18 | ReadOnlySpan prev2 = prev1; 19 | 20 | static int Score(char match) 21 | { 22 | if (char.IsLower(match)) 23 | { 24 | return match - '`'; 25 | } 26 | 27 | return match - '&'; 28 | } 29 | 30 | while (hasMore) 31 | { 32 | var end = span.IndexOf('\n'); 33 | ReadOnlySpan full; 34 | 35 | if (end == -1) 36 | { 37 | hasMore = false; 38 | end = span.Length; 39 | full = span[0..end]; 40 | } 41 | else 42 | { 43 | full = span[0..end]; 44 | span = span[(end + 1)..]; 45 | } 46 | 47 | var half = end / 2; 48 | var a = full[..half]; 49 | var b = full[half..]; 50 | 51 | part1 += Score(a[a.IndexOfAny(b)]); 52 | 53 | switch (line++ % 3) 54 | { 55 | case 0: prev1 = full; break; 56 | case 1: prev2 = full; break; 57 | case 2: 58 | foreach (var c in full) 59 | { 60 | if (prev1.IndexOf(c) >= 0 && prev2.IndexOf(c) >= 0) 61 | { 62 | part2 += Score(c); 63 | break; 64 | } 65 | } 66 | break; 67 | } 68 | } 69 | 70 | return (part1.ToString(), part2.ToString()); 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day4.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode; 2 | 3 | [Answer(4)] 4 | public class Day4 : IAnswer 5 | { 6 | public (string Part1, string Part2) Solve(string input) 7 | { 8 | var i = 0; 9 | var length = input.Length; 10 | var part1 = 0; 11 | var part2 = 0; 12 | 13 | int ParseIntUntil(char c) 14 | { 15 | var result = 0; 16 | 17 | do 18 | { 19 | var t = input[i++]; 20 | 21 | if (t == c) 22 | { 23 | break; 24 | } 25 | 26 | result = 10 * result + t - '0'; 27 | } 28 | while (i < length); 29 | 30 | return result; 31 | } 32 | 33 | while (i < length) 34 | { 35 | var a = ParseIntUntil('-'); 36 | var b = ParseIntUntil(','); 37 | var c = ParseIntUntil('-'); 38 | var d = ParseIntUntil('\n'); 39 | 40 | if ((a >= c && b <= d) || (c >= a && d <= b)) 41 | { 42 | part1++; 43 | } 44 | 45 | if (b >= c && a <= d) 46 | { 47 | part2++; 48 | } 49 | } 50 | 51 | return (part1.ToString(), part2.ToString()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day6.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode; 4 | 5 | [Answer(6)] 6 | public class Day6 : IAnswer 7 | { 8 | public (string Part1, string Part2) Solve(string input) 9 | { 10 | int SlideThatWindow(int size) 11 | { 12 | var start = 0; 13 | 14 | for (var end = 0; end < input.Length; end++) 15 | { 16 | var c = input[end]; 17 | 18 | for (var j = start; j < end; j++) 19 | { 20 | if (c == input[j]) 21 | { 22 | start = j + 1; 23 | break; 24 | } 25 | } 26 | 27 | if (1 + end - start == size) 28 | { 29 | return end + 1; 30 | } 31 | } 32 | 33 | return 0; 34 | } 35 | 36 | var part1 = SlideThatWindow(4); 37 | var part2 = SlideThatWindow(14); 38 | 39 | return (part1.ToString(), part2.ToString()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day8.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode; 2 | 3 | [Answer(8)] 4 | public class Day8 : IAnswer 5 | { 6 | public (string Part1, string Part2) Solve(string input) 7 | { 8 | var width = input.IndexOf('\n'); 9 | var height = input.Length / width; 10 | 11 | var part1 = width + width + height + height - 4; 12 | var part2 = 0; 13 | 14 | char Tree(int x, int y) => input[y * (width + 1) + x]; 15 | 16 | for (var x = 1; x < width - 1; x++) 17 | { 18 | for (var y = 1; y < height - 1; y++) 19 | { 20 | var tree = Tree(x, y); 21 | var visible = 4; 22 | var score1 = 0; 23 | var score2 = 0; 24 | var score3 = 0; 25 | var score4 = 0; 26 | 27 | for (var a = x - 1; a >= 0; a--) 28 | { 29 | score1++; 30 | 31 | if (Tree(a, y) >= tree) 32 | { 33 | visible--; 34 | break; 35 | } 36 | } 37 | 38 | for (var a = x + 1; a < width; a++) 39 | { 40 | score2++; 41 | 42 | if (Tree(a, y) >= tree) 43 | { 44 | visible--; 45 | break; 46 | } 47 | } 48 | 49 | for (var a = y - 1; a >= 0; a--) 50 | { 51 | score3++; 52 | 53 | if (Tree(x, a) >= tree) 54 | { 55 | visible--; 56 | break; 57 | } 58 | } 59 | 60 | for (var a = y + 1; a < height; a++) 61 | { 62 | score4++; 63 | 64 | if (Tree(x, a) >= tree) 65 | { 66 | visible--; 67 | break; 68 | } 69 | } 70 | 71 | if (visible > 0) 72 | { 73 | part1++; 74 | } 75 | 76 | var totalScore = score1 * score2 * score3 * score4; 77 | 78 | if (part2 < totalScore) 79 | { 80 | part2 = totalScore; 81 | } 82 | } 83 | } 84 | 85 | return (part1.ToString(), part2.ToString()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /2022/Answers/Solutions/Day9.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(9)] 7 | public class Day9 : IAnswer 8 | { 9 | public (string Part1, string Part2) Solve(string input) 10 | { 11 | var knots = new (int X, int Y)[10]; 12 | var visited1 = new HashSet(); 13 | var visited2 = new HashSet(); 14 | 15 | for (var i = 0; i < input.Length; i++) 16 | { 17 | var dir = input[i++] - '0'; 18 | var steps = 0; 19 | 20 | do 21 | { 22 | var t = input[++i]; 23 | 24 | if (t == '\n') 25 | { 26 | break; 27 | } 28 | 29 | steps = 10 * steps + t - '0'; 30 | } 31 | while (i < input.Length - 1); 32 | 33 | while (steps-- > 0) 34 | { 35 | switch (dir) 36 | { 37 | case 'U' - '0': knots[0].X++; break; 38 | case 'D' - '0': knots[0].X--; break; 39 | case 'R' - '0': knots[0].Y++; break; 40 | case 'L' - '0': knots[0].Y--; break; 41 | default: throw new Exception(); 42 | } 43 | 44 | for (var knot = 1; knot < 10; knot++) 45 | { 46 | var dX = knots[knot - 1].X - knots[knot].X; 47 | var dY = knots[knot - 1].Y - knots[knot].Y; 48 | 49 | if (dX > 1 || dY > 1 || dX < -1 || dY < -1) 50 | { 51 | knots[knot].X += Math.Sign(dX); 52 | knots[knot].Y += Math.Sign(dY); 53 | } 54 | } 55 | 56 | visited1.Add(knots[1].X * 10000 + knots[1].Y); 57 | visited2.Add(knots[9].X * 10000 + knots[9].Y); 58 | } 59 | } 60 | 61 | var part1 = visited1.Count; 62 | var part2 = visited2.Count; 63 | 64 | return (part1.ToString(), part2.ToString()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /2022/DataExamples/answers.txt: -------------------------------------------------------------------------------- 1 | 24000 | 45000 2 | 15 | 12 3 | 157 | 70 4 | 2 | 4 5 | CMZ | MCD 6 | 7 | 19 7 | 95437 | 24933642 8 | 21 | 8 9 | 88 | 36 10 | 13140 | \n##..##..##..##..##..##..##..##..##..##..\n###...###...###...###...###...###...###.\n####....####....####....####....####....\n#####.....#####.....#####.....#####.....\n######......######......######......####\n#######.......#######.......#######.....\n 11 | 10605 | 2713310158 12 | 31 | 29 13 | 13 | 140 14 | 24 | 93 15 | 26 | 56000011 16 | 1651 | 1707 17 | 3068 | 1514285714288 18 | 64 | 58 19 | 33 | 3472 20 | 3 | 1623178306 21 | 152 | 301 22 | 6032 | 5031 23 | 110 | 20 24 | 18 | 54 25 | 2=-1=0 | Woo! 26 | -------------------------------------------------------------------------------- /2022/DataExamples/day1.txt: -------------------------------------------------------------------------------- 1 | 1000 2 | 2000 3 | 3000 4 | 5 | 4000 6 | 7 | 5000 8 | 6000 9 | 10 | 7000 11 | 8000 12 | 9000 13 | 14 | 10000 15 | -------------------------------------------------------------------------------- /2022/DataExamples/day10.txt: -------------------------------------------------------------------------------- 1 | addx 15 2 | addx -11 3 | addx 6 4 | addx -3 5 | addx 5 6 | addx -1 7 | addx -8 8 | addx 13 9 | addx 4 10 | noop 11 | addx -1 12 | addx 5 13 | addx -1 14 | addx 5 15 | addx -1 16 | addx 5 17 | addx -1 18 | addx 5 19 | addx -1 20 | addx -35 21 | addx 1 22 | addx 24 23 | addx -19 24 | addx 1 25 | addx 16 26 | addx -11 27 | noop 28 | noop 29 | addx 21 30 | addx -15 31 | noop 32 | noop 33 | addx -3 34 | addx 9 35 | addx 1 36 | addx -3 37 | addx 8 38 | addx 1 39 | addx 5 40 | noop 41 | noop 42 | noop 43 | noop 44 | noop 45 | addx -36 46 | noop 47 | addx 1 48 | addx 7 49 | noop 50 | noop 51 | noop 52 | addx 2 53 | addx 6 54 | noop 55 | noop 56 | noop 57 | noop 58 | noop 59 | addx 1 60 | noop 61 | noop 62 | addx 7 63 | addx 1 64 | noop 65 | addx -13 66 | addx 13 67 | addx 7 68 | noop 69 | addx 1 70 | addx -33 71 | noop 72 | noop 73 | noop 74 | addx 2 75 | noop 76 | noop 77 | noop 78 | addx 8 79 | noop 80 | addx -1 81 | addx 2 82 | addx 1 83 | noop 84 | addx 17 85 | addx -9 86 | addx 1 87 | addx 1 88 | addx -3 89 | addx 11 90 | noop 91 | noop 92 | addx 1 93 | noop 94 | addx 1 95 | noop 96 | noop 97 | addx -13 98 | addx -19 99 | addx 1 100 | addx 3 101 | addx 26 102 | addx -30 103 | addx 12 104 | addx -1 105 | addx 3 106 | addx 1 107 | noop 108 | noop 109 | noop 110 | addx -9 111 | addx 18 112 | addx 1 113 | addx 2 114 | noop 115 | noop 116 | addx 9 117 | noop 118 | noop 119 | noop 120 | addx -1 121 | addx 2 122 | addx -37 123 | addx 1 124 | addx 3 125 | noop 126 | addx 15 127 | addx -21 128 | addx 22 129 | addx -6 130 | addx 1 131 | noop 132 | addx 2 133 | addx 1 134 | noop 135 | addx -10 136 | noop 137 | noop 138 | addx 20 139 | addx 1 140 | addx 2 141 | addx 2 142 | addx -6 143 | addx -11 144 | noop 145 | noop 146 | noop 147 | -------------------------------------------------------------------------------- /2022/DataExamples/day11.txt: -------------------------------------------------------------------------------- 1 | Monkey 0: 2 | Starting items: 79, 98 3 | Operation: new = old * 19 4 | Test: divisible by 23 5 | If true: throw to monkey 2 6 | If false: throw to monkey 3 7 | 8 | Monkey 1: 9 | Starting items: 54, 65, 75, 74 10 | Operation: new = old + 6 11 | Test: divisible by 19 12 | If true: throw to monkey 2 13 | If false: throw to monkey 0 14 | 15 | Monkey 2: 16 | Starting items: 79, 60, 97 17 | Operation: new = old * old 18 | Test: divisible by 13 19 | If true: throw to monkey 1 20 | If false: throw to monkey 3 21 | 22 | Monkey 3: 23 | Starting items: 74 24 | Operation: new = old + 3 25 | Test: divisible by 17 26 | If true: throw to monkey 0 27 | If false: throw to monkey 1 28 | -------------------------------------------------------------------------------- /2022/DataExamples/day12.txt: -------------------------------------------------------------------------------- 1 | Sabqponm 2 | abcryxxl 3 | accszExk 4 | acctuvwj 5 | abdefghi 6 | -------------------------------------------------------------------------------- /2022/DataExamples/day13.txt: -------------------------------------------------------------------------------- 1 | [1,1,3,1,1] 2 | [1,1,5,1,1] 3 | 4 | [[1],[2,3,4]] 5 | [[1],4] 6 | 7 | [9] 8 | [[8,7,6]] 9 | 10 | [[4,4],4,4] 11 | [[4,4],4,4,4] 12 | 13 | [7,7,7,7] 14 | [7,7,7] 15 | 16 | [] 17 | [3] 18 | 19 | [[[]]] 20 | [[]] 21 | 22 | [1,[2,[3,[4,[5,6,7]]]],8,9] 23 | [1,[2,[3,[4,[5,6,0]]]],8,9] 24 | -------------------------------------------------------------------------------- /2022/DataExamples/day14.txt: -------------------------------------------------------------------------------- 1 | 498,4 -> 498,6 -> 496,6 2 | 503,4 -> 502,4 -> 502,9 -> 494,9 3 | -------------------------------------------------------------------------------- /2022/DataExamples/day15.txt: -------------------------------------------------------------------------------- 1 | Sensor at x=2, y=18: closest beacon is at x=-2, y=15 2 | Sensor at x=9, y=16: closest beacon is at x=10, y=16 3 | Sensor at x=13, y=2: closest beacon is at x=15, y=3 4 | Sensor at x=12, y=14: closest beacon is at x=10, y=16 5 | Sensor at x=10, y=20: closest beacon is at x=10, y=16 6 | Sensor at x=14, y=17: closest beacon is at x=10, y=16 7 | Sensor at x=8, y=7: closest beacon is at x=2, y=10 8 | Sensor at x=2, y=0: closest beacon is at x=2, y=10 9 | Sensor at x=0, y=11: closest beacon is at x=2, y=10 10 | Sensor at x=20, y=14: closest beacon is at x=25, y=17 11 | Sensor at x=17, y=20: closest beacon is at x=21, y=22 12 | Sensor at x=16, y=7: closest beacon is at x=15, y=3 13 | Sensor at x=14, y=3: closest beacon is at x=15, y=3 14 | Sensor at x=20, y=1: closest beacon is at x=15, y=3 15 | -------------------------------------------------------------------------------- /2022/DataExamples/day16.txt: -------------------------------------------------------------------------------- 1 | Valve AA has flow rate=0; tunnels lead to valves DD, II, BB 2 | Valve BB has flow rate=13; tunnels lead to valves CC, AA 3 | Valve CC has flow rate=2; tunnels lead to valves DD, BB 4 | Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE 5 | Valve EE has flow rate=3; tunnels lead to valves FF, DD 6 | Valve FF has flow rate=0; tunnels lead to valves EE, GG 7 | Valve GG has flow rate=0; tunnels lead to valves FF, HH 8 | Valve HH has flow rate=22; tunnel leads to valve GG 9 | Valve II has flow rate=0; tunnels lead to valves AA, JJ 10 | Valve JJ has flow rate=21; tunnel leads to valve II 11 | -------------------------------------------------------------------------------- /2022/DataExamples/day17.txt: -------------------------------------------------------------------------------- 1 | >>><<><>><<<>><>>><<<>>><<<><<<>><>><<>> 2 | -------------------------------------------------------------------------------- /2022/DataExamples/day18.txt: -------------------------------------------------------------------------------- 1 | 2,2,2 2 | 1,2,2 3 | 3,2,2 4 | 2,1,2 5 | 2,3,2 6 | 2,2,1 7 | 2,2,3 8 | 2,2,4 9 | 2,2,6 10 | 1,2,5 11 | 3,2,5 12 | 2,1,5 13 | 2,3,5 14 | -------------------------------------------------------------------------------- /2022/DataExamples/day19.txt: -------------------------------------------------------------------------------- 1 | Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian. 2 | Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian. 3 | -------------------------------------------------------------------------------- /2022/DataExamples/day2.txt: -------------------------------------------------------------------------------- 1 | A Y 2 | B X 3 | C Z 4 | -------------------------------------------------------------------------------- /2022/DataExamples/day20.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | -3 4 | 3 5 | -2 6 | 0 7 | 4 8 | -------------------------------------------------------------------------------- /2022/DataExamples/day21.txt: -------------------------------------------------------------------------------- 1 | root: pppw + sjmn 2 | dbpl: 5 3 | cczh: sllz + lgvd 4 | zczc: 2 5 | ptdq: humn - dvpt 6 | dvpt: 3 7 | lfqf: 4 8 | humn: 5 9 | ljgn: 2 10 | sjmn: drzm * dbpl 11 | sllz: 4 12 | pppw: cczh / lfqf 13 | lgvd: ljgn * ptdq 14 | drzm: hmdt - zczc 15 | hmdt: 32 16 | -------------------------------------------------------------------------------- /2022/DataExamples/day22.txt: -------------------------------------------------------------------------------- 1 | ...# 2 | .#.. 3 | #... 4 | .... 5 | ...#.......# 6 | ........#... 7 | ..#....#.... 8 | ..........#. 9 | ...#.... 10 | .....#.. 11 | .#...... 12 | ......#. 13 | 14 | 10R5L5R10L4R5L5 15 | -------------------------------------------------------------------------------- /2022/DataExamples/day23.txt: -------------------------------------------------------------------------------- 1 | ....#.. 2 | ..###.# 3 | #...#.# 4 | .#...## 5 | #.###.. 6 | ##.#.## 7 | .#..#.. 8 | -------------------------------------------------------------------------------- /2022/DataExamples/day24.txt: -------------------------------------------------------------------------------- 1 | #.###### 2 | #>>.<^<# 3 | #.<..<<# 4 | #>v.><># 5 | #<^v^^># 6 | ######.# 7 | -------------------------------------------------------------------------------- /2022/DataExamples/day25.txt: -------------------------------------------------------------------------------- 1 | 1=-0-2 2 | 12111 3 | 2=0= 4 | 21 5 | 2=01 6 | 111 7 | 20012 8 | 112 9 | 1=-1= 10 | 1-12 11 | 12 12 | 1= 13 | 122 14 | -------------------------------------------------------------------------------- /2022/DataExamples/day3.txt: -------------------------------------------------------------------------------- 1 | vJrwpWtwJgWrhcsFMMfFFhFp 2 | jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL 3 | PmmdzqPrVvPwwTWBwg 4 | wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn 5 | ttgJtRGJQctTZtZT 6 | CrZsJsPPZsGzwwsLwLmpwMDw 7 | -------------------------------------------------------------------------------- /2022/DataExamples/day4.txt: -------------------------------------------------------------------------------- 1 | 2-4,6-8 2 | 2-3,4-5 3 | 5-7,7-9 4 | 2-8,3-7 5 | 6-6,4-6 6 | 2-6,4-8 7 | -------------------------------------------------------------------------------- /2022/DataExamples/day5.txt: -------------------------------------------------------------------------------- 1 | [D] 2 | [N] [C] 3 | [Z] [M] [P] 4 | 1 2 3 5 | 6 | move 1 from 2 to 1 7 | move 3 from 1 to 3 8 | move 2 from 2 to 1 9 | move 1 from 1 to 2 10 | -------------------------------------------------------------------------------- /2022/DataExamples/day6.txt: -------------------------------------------------------------------------------- 1 | mjqjpqmgbljsphdztnvjfqwrcgsmlb 2 | -------------------------------------------------------------------------------- /2022/DataExamples/day7.txt: -------------------------------------------------------------------------------- 1 | $ cd / 2 | $ ls 3 | dir a 4 | 14848514 b.txt 5 | 8504156 c.dat 6 | dir d 7 | $ cd a 8 | $ ls 9 | dir e 10 | 29116 f 11 | 2557 g 12 | 62596 h.lst 13 | $ cd e 14 | $ ls 15 | 584 i 16 | $ cd .. 17 | $ cd .. 18 | $ cd d 19 | $ ls 20 | 4060174 j 21 | 8033020 d.log 22 | 5626152 d.ext 23 | 7214296 k 24 | -------------------------------------------------------------------------------- /2022/DataExamples/day8.txt: -------------------------------------------------------------------------------- 1 | 30373 2 | 25512 3 | 65332 4 | 33549 5 | 35390 6 | -------------------------------------------------------------------------------- /2022/DataExamples/day9.txt: -------------------------------------------------------------------------------- 1 | R 5 2 | U 8 3 | L 8 4 | D 3 5 | R 17 6 | D 10 7 | L 25 8 | U 20 9 | -------------------------------------------------------------------------------- /2022/SolverGenerator/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Profile 1": { 4 | "commandName": "DebugRoslynComponent", 5 | "targetProject": "..\\Answers\\AdventOfCode.csproj" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /2022/SolverGenerator/SolverGenerator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | true 5 | 6 | 7 | 8 | 9 | all 10 | runtime; build; native; contentfiles; analyzers; buildtransitive 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /2022/Tests/SolutionTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using System.Threading.Tasks; 3 | using System.Collections.Generic; 4 | 5 | namespace AdventOfCode.Tests; 6 | 7 | public class SolutionTests 8 | { 9 | public static IEnumerable GetData() 10 | { 11 | Solver.GetAnswers(1).GetAwaiter().GetResult(); // Load answers so Solver.AvailableDays is set 12 | 13 | for (var day = 1; day <= Solver.AvailableDays; day++) 14 | { 15 | yield return new object[] { day }; 16 | } 17 | } 18 | 19 | [Theory] 20 | [MemberData(nameof(GetData))] 21 | public async Task TestDay(int day) 22 | { 23 | var data = await Solver.LoadData(day); 24 | var (part1, part2) = Solver.Solve(day, data); 25 | 26 | var (part1answer, part2answer) = await Solver.GetAnswers(day); 27 | 28 | Assert.Equal(part1answer, part1); 29 | Assert.Equal(part2answer, part2); 30 | 31 | var example = await Solver.SolveExample(day); 32 | Assert.Equal(example.Item1, example.Item2); 33 | Assert.Equal(example.Item3, example.Item4); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /2022/Tests/Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | enable 5 | false 6 | true 7 | 8 | 9 | 10 | 11 | 12 | runtime; build; native; contentfiles; analyzers; buildtransitive 13 | all 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /2022/prep.ps1: -------------------------------------------------------------------------------- 1 | $Day = (Get-Date).Day 2 | 3 | New-Item -Path "Data" -Name "day$Day.txt" -ItemType "file" 4 | New-Item -Path "DataExamples" -Name "day$Day.txt" -ItemType "file" 5 | 6 | $Path = "Answers\Solutions\Day$Day.cs" 7 | 8 | if ((Test-Path $Path) -eq $False) { 9 | ((Get-Content "Answers\Solutions\Day0.cs" -Raw) -replace [regex]::escape("[Answer(0)]"),"[Answer($Day)]" -replace "class Day0","class Day$Day") | Set-Content -NoNewline -Path $Path 10 | } 11 | -------------------------------------------------------------------------------- /2023/AdventOfCode.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33103.184 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "Answers\AdventOfCode.csproj", "{D9537297-BC8C-4803-B23A-6D4FD42B2B95}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SolverGenerator", "SolverGenerator\SolverGenerator.csproj", "{F845D75F-AB5F-4AE1-A095-00548F5123FB}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {F845D75F-AB5F-4AE1-A095-00548F5123FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {F845D75F-AB5F-4AE1-A095-00548F5123FB}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {F845D75F-AB5F-4AE1-A095-00548F5123FB}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {F845D75F-AB5F-4AE1-A095-00548F5123FB}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {C10091A0-1CB1-49F4-A48B-9457CEFA4857} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /2023/Answers/AdventOfCode.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net8.0 5 | AdventOfCode 6 | enable 7 | false 8 | CA1822 9 | true 10 | true 11 | true 12 | true 13 | true 14 | $(DefineConstants);NO_BENCHMARK 15 | x64 16 | win-x64 17 | 18 | 19 | 20 | Data\%(Filename)%(Extension) 21 | 22 | 23 | DataExamples\%(Filename)%(Extension) 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /2023/Answers/AnswerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode; 4 | 5 | [AttributeUsage(AttributeTargets.Class)] 6 | class AnswerAttribute : Attribute 7 | { 8 | public int Day { get; init; } 9 | public bool Slow { get; init; } 10 | public AnswerAttribute(int day) => Day = day; 11 | public AnswerAttribute(int day, bool slow) 12 | { 13 | Day = day; 14 | Slow = slow; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /2023/Answers/BenchmarkSolver.cs: -------------------------------------------------------------------------------- 1 | #if !NO_BENCHMARK 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace AdventOfCode; 5 | 6 | [MemoryDiagnoser] 7 | public class BenchmarkSolver 8 | { 9 | //[Params(1)] 10 | public int Day { get; set; } 11 | 12 | private string Data = string.Empty; 13 | 14 | [GlobalSetup] 15 | public void Setup() 16 | { 17 | Day = System.DateTime.Today.Day; 18 | Data = Solver.Data[Day]; 19 | } 20 | 21 | [Benchmark] 22 | public Solution Solve() 23 | { 24 | return Solver.Solve(Day, Data); 25 | } 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /2023/Answers/IAnswer.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode; 2 | 3 | public interface IAnswer 4 | { 5 | public Solution Solve(string input); 6 | } 7 | -------------------------------------------------------------------------------- /2023/Answers/Solution.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode; 2 | 3 | public record Solution(string Part1, string Part2); 4 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day0.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode; 4 | 5 | [Answer(0)] 6 | public class Day0 : IAnswer 7 | { 8 | public Solution Solve(string input) 9 | { 10 | var part1 = 0; 11 | var part2 = 0; 12 | 13 | return new(part1.ToString(), part2.ToString()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(1)] 7 | public class Day1 : IAnswer 8 | { 9 | public Solution Solve(string input) 10 | { 11 | var part1 = 0; 12 | var part2 = 0; 13 | 14 | foreach (var line in input.AsSpan().EnumerateLines()) 15 | { 16 | part1 += Score(line); 17 | } 18 | 19 | var sb = new StringBuilder(input) 20 | .Replace("one", "o1e") 21 | .Replace("two", "t2o") 22 | .Replace("three", "thr3e") 23 | .Replace("four", "fo4r") 24 | .Replace("five", "fi5e") 25 | .Replace("six", "s6x") 26 | .Replace("seven", "se7en") 27 | .Replace("eight", "ei8ht") 28 | .Replace("nine", "n9ne"); 29 | 30 | foreach (var line in sb.ToString().AsSpan().EnumerateLines()) 31 | { 32 | part2 += Score(line); 33 | } 34 | 35 | return new(part1.ToString(), part2.ToString()); 36 | } 37 | 38 | private static int Score(ReadOnlySpan line) 39 | { 40 | var first = line[line.IndexOfAnyInRange('0', '9')] - '0'; 41 | var last = line[line.LastIndexOfAnyInRange('0', '9')] - '0'; 42 | 43 | return first * 10 + last; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day13.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode; 4 | 5 | [Answer(13)] 6 | public class Day13 : IAnswer 7 | { 8 | public Solution Solve(string input) 9 | { 10 | var part1 = 0; 11 | var part2 = 0; 12 | 13 | var remainder = input.AsSpan(); 14 | 15 | do 16 | { 17 | var maze = remainder; 18 | var nl = remainder.IndexOf("\n\n"); 19 | 20 | if (nl == -1) 21 | { 22 | remainder = null; 23 | } 24 | else 25 | { 26 | maze = remainder[0..nl]; 27 | remainder = remainder[(nl + 2)..]; 28 | } 29 | 30 | var width = maze.IndexOf('\n'); 31 | var stride = width + 1; 32 | var height = (maze.Length + 1) / stride; 33 | 34 | for (var x = 0; x < width - 1; x++) 35 | { 36 | var diff = 0; 37 | 38 | for (var y = 0; y < height; y++) 39 | { 40 | for (var d = 0; x >= d && x + d + 1 < width; d++) 41 | { 42 | if (maze[y * stride + x - d] != maze[y * stride + x + d + 1] && ++diff > 0) 43 | { 44 | break; 45 | } 46 | } 47 | } 48 | 49 | if (diff == 0) 50 | { 51 | part1 += x + 1; 52 | } 53 | else if (diff == 1) 54 | { 55 | part2 += x + 1; 56 | } 57 | } 58 | 59 | for (var y = 0; y < height - 1; y++) 60 | { 61 | var diff = 0; 62 | 63 | for (var x = 0; x < width; x++) 64 | { 65 | for (var d = 0; y >= d && y + d + 1 < height; d++) 66 | { 67 | if (maze[(y - d) * stride + x] != maze[(y + d + 1) * stride + x] && ++diff > 0) 68 | { 69 | break; 70 | } 71 | } 72 | } 73 | 74 | if (diff == 0) 75 | { 76 | part1 += (y + 1) * 100; 77 | } 78 | else if (diff == 1) 79 | { 80 | part2 += (y + 1) * 100; 81 | } 82 | } 83 | } 84 | while (remainder != null); 85 | 86 | return new(part1.ToString(), part2.ToString()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day15.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace AdventOfCode; 4 | 5 | [Answer(15)] 6 | public class Day15 : IAnswer 7 | { 8 | record struct Lens(string Label, int Value); 9 | 10 | public Solution Solve(string input) 11 | { 12 | var part1 = 0; 13 | var part2 = 0; 14 | 15 | var init = input.Split(','); 16 | var boxes = new List[256]; 17 | 18 | for (var i = 0; i < boxes.Length; i++) 19 | { 20 | boxes[i] = []; 21 | } 22 | 23 | foreach (var line in init) 24 | { 25 | var currentValue = 0; 26 | 27 | foreach (var c in line) 28 | { 29 | currentValue += (byte)c; 30 | currentValue *= 17; 31 | currentValue %= 256; 32 | } 33 | 34 | part1 += currentValue; 35 | 36 | currentValue = 0; 37 | var label = line; 38 | 39 | for (var i = 0; i < line.Length; i++) 40 | { 41 | var c = line[i]; 42 | 43 | if (c is '-' or '=') 44 | { 45 | label = line[..i]; 46 | break; 47 | } 48 | 49 | currentValue += (byte)c; 50 | currentValue *= 17; 51 | currentValue %= 256; 52 | } 53 | 54 | var box = boxes[currentValue]; 55 | var index = box.FindIndex(c => c.Label == label); 56 | 57 | if (index == -1) 58 | { 59 | if (line[^1] == '-') 60 | { 61 | continue; 62 | } 63 | 64 | box.Add(new(label, line[^1] - '0')); 65 | } 66 | else if (line[^1] == '-') 67 | { 68 | box.RemoveAt(index); 69 | } 70 | else 71 | { 72 | box[index] = new(label, line[^1] - '0'); 73 | } 74 | } 75 | 76 | for (var boxId = 0; boxId < boxes.Length; boxId++) 77 | { 78 | var box = boxes[boxId]; 79 | 80 | for (var slot = 0; slot < box.Count; slot++) 81 | { 82 | part2 += (boxId + 1) * (slot + 1) * box[slot].Value; 83 | } 84 | } 85 | 86 | return new(part1.ToString(), part2.ToString()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(2)] 7 | public class Day2 : IAnswer 8 | { 9 | public Solution Solve(string input) 10 | { 11 | var part1 = 0; 12 | var part2 = 0; 13 | var gameId = 0; 14 | 15 | foreach (var line in input.AsSpan().EnumerateLines()) 16 | { 17 | var part1Score = ++gameId; 18 | var maxR = 0; 19 | var maxG = 0; 20 | var maxB = 0; 21 | int limit; 22 | 23 | for (var i = line.IndexOf(':') + 2; i < line.Length; i++) 24 | { 25 | var num = line[i] - '0'; 26 | var next = line[i + 1]; 27 | 28 | if (next != ' ') 29 | { 30 | i++; 31 | num = 10 * num + next - '0'; 32 | } 33 | 34 | switch (line[i + 2]) 35 | { 36 | case 'r': 37 | i += 6; 38 | limit = 12; 39 | maxR = Math.Max(maxR, num); 40 | break; 41 | 42 | case 'g': 43 | i += 8; 44 | limit = 13; 45 | maxG = Math.Max(maxG, num); 46 | break; 47 | 48 | case 'b': 49 | i += 7; 50 | limit = 14; 51 | maxB = Math.Max(maxB, num); 52 | break; 53 | 54 | default: 55 | throw new UnreachableException(); 56 | } 57 | 58 | if (num > limit) 59 | { 60 | part1Score = 0; 61 | } 62 | } 63 | 64 | part1 += part1Score; 65 | part2 += maxR * maxG * maxB; 66 | } 67 | 68 | return new(part1.ToString(), part2.ToString()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day25.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace AdventOfCode; 6 | 7 | [Answer(25)] 8 | public class Day25 : IAnswer 9 | { 10 | public Solution Solve(string input) 11 | { 12 | var graph = new Dictionary>(); 13 | 14 | foreach (var line in input.AsSpan().EnumerateLines()) 15 | { 16 | var colon = line.IndexOf(':'); 17 | var name = line[..colon].ToString(); 18 | var destinations = line[(colon + 2)..].ToString().Split(' ').ToHashSet(); 19 | 20 | if (!graph.TryGetValue(name, out var list1)) 21 | { 22 | list1 = []; 23 | graph[name] = list1; 24 | } 25 | 26 | foreach (var node in destinations) 27 | { 28 | list1.Add(node); 29 | 30 | if (!graph.TryGetValue(node, out var list2)) 31 | { 32 | list2 = []; 33 | graph[node] = list2; 34 | } 35 | 36 | list2.Add(name); 37 | } 38 | } 39 | 40 | var edges = new HashSet(graph.Keys); 41 | 42 | int Count(string node) => graph[node].Count(n => !edges.Contains(n)); 43 | 44 | while (edges.Sum(Count) != 3) 45 | { 46 | edges.Remove(edges.MaxBy(Count)!); 47 | } 48 | 49 | var part1 = edges.Count * graph.Keys.Except(edges).Count(); 50 | var part2 = 0; 51 | 52 | return new(part1.ToString(), part2.ToString()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(3)] 7 | public class Day3 : IAnswer 8 | { 9 | public Solution Solve(string l) 10 | { 11 | var part1 = 0; 12 | var part2 = 0; 13 | 14 | var input = l.AsSpan(); 15 | var size = input.IndexOf('\n') + 1; 16 | var search = SearchValues.Create("\n.0123456789"); 17 | var offset = 0; 18 | int index; 19 | 20 | while ((index = input[offset..].IndexOfAnyExcept(search)) != -1) 21 | { 22 | offset += index; 23 | 24 | var (y, x) = Math.DivRem(offset, size); 25 | var isGear = input[offset] == '*'; 26 | var leftNumber = 0; 27 | 28 | offset += 1; 29 | 30 | for (int y2 = y - 1; y2 <= y + 1; y2++) 31 | { 32 | for (int x2 = x - 1; x2 <= x + 1; x2++) 33 | { 34 | if (!char.IsAsciiDigit(input[y2 * size + x2])) 35 | { 36 | continue; 37 | } 38 | 39 | while (--x2 >= 0 && char.IsAsciiDigit(input[y2 * size + x2])) 40 | { 41 | // 42 | } 43 | 44 | var number = 0; 45 | 46 | do 47 | { 48 | number = number * 10 + (input[y2 * size + ++x2] - '0'); 49 | } 50 | while (char.IsAsciiDigit(input[y2 * size + x2 + 1])); 51 | 52 | part1 += number; 53 | 54 | if (isGear) 55 | { 56 | if (leftNumber > 0) 57 | { 58 | part2 += leftNumber * number; 59 | } 60 | else 61 | { 62 | leftNumber = number; 63 | } 64 | } 65 | } 66 | } 67 | } 68 | 69 | return new(part1.ToString(), part2.ToString()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode; 4 | 5 | [Answer(4)] 6 | public class Day4 : IAnswer 7 | { 8 | public Solution Solve(string inputStr) 9 | { 10 | var input = inputStr.AsSpan(); 11 | var part1 = 0; 12 | var part2 = 0; 13 | 14 | var offset = input.IndexOf(':') + 2; 15 | var offsetSplit = input.IndexOf('|') + 2; 16 | var offsetLine = input.IndexOf('\n') + 1; 17 | 18 | var winnersCount = (offsetSplit - offset) / 3; 19 | var guessesCount = (offsetLine - (offsetSplit - 2)) / 3; 20 | var winningNumbers = new int[winnersCount].AsSpan(); 21 | 22 | var cardCount = input.Length / offsetLine; 23 | var cards = new int[cardCount + winnersCount]; 24 | cards.AsSpan().Fill(1); 25 | 26 | static int GetNumber(ReadOnlySpan line) 27 | { 28 | var a = line[0] - '0'; 29 | var b = line[1] - '0'; 30 | 31 | return a < 0 ? b : a * 10 + b; 32 | } 33 | 34 | for (int cardId = 0; cardId <= cardCount; cardId++) 35 | { 36 | var winners = 0; 37 | var off = offsetLine * cardId + offset; 38 | 39 | for (var i = 0; i < winnersCount; i++) 40 | { 41 | winningNumbers[i] = GetNumber(input[off..]); 42 | off += 3; 43 | } 44 | 45 | off += 2; 46 | 47 | for (var i = 0; i < guessesCount; i++) 48 | { 49 | var number = GetNumber(input[off..]); 50 | off += 3; 51 | 52 | if (winningNumbers.Contains(number)) 53 | { 54 | winners++; 55 | } 56 | } 57 | 58 | var previousCards = cards[cardId]; 59 | part2 += previousCards; 60 | 61 | if (winners > 0) 62 | { 63 | part1 += 1 << (winners - 1); 64 | 65 | for (var c = cardId + 1; c <= cardId + winners; c++) 66 | { 67 | cards[c] += previousCards; 68 | } 69 | } 70 | } 71 | 72 | return new(part1.ToString(), part2.ToString()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day6.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(6)] 7 | public class Day6 : IAnswer 8 | { 9 | public Solution Solve(string input) 10 | { 11 | var part1 = 1L; 12 | var part2 = 0L; 13 | 14 | var lines = input.Split('\n'); 15 | var times = lines[0]["Time: ".Length..].Split(' ').Where(x => x.Length > 0).Select(int.Parse).ToArray(); 16 | var dists = lines[1]["Distance: ".Length..].Split(' ').Where(x => x.Length > 0).Select(int.Parse).ToArray(); 17 | 18 | static long Solve(long time, long dist) 19 | { 20 | var firstWinningTime = (long)Math.Ceiling((time - Math.Sqrt(time * time - 4 * (dist + 1))) / 2); 21 | return time - firstWinningTime * 2 + 1; 22 | } 23 | 24 | for (var i = 0; i < times.Length; i++) 25 | { 26 | var time = times[i]; 27 | var dist = dists[i]; 28 | part1 *= Solve(time, dist); 29 | } 30 | 31 | { 32 | var time = long.Parse(string.Concat(times)); 33 | var dist = long.Parse(string.Concat(dists)); 34 | part2 = Solve(time, dist); 35 | } 36 | 37 | return new(part1.ToString(), part2.ToString()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /2023/Answers/Solutions/Day9.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(9)] 7 | public class Day9 : IAnswer 8 | { 9 | public Solution Solve(string input) 10 | { 11 | var part1 = 0; 12 | var part2 = 0; 13 | 14 | var sequence = new List(32); 15 | 16 | foreach (var line in input.AsSpan().EnumerateLines()) 17 | { 18 | var remainder = line; 19 | 20 | do 21 | { 22 | var result = 0; 23 | var i = 0; 24 | var sign = 1; 25 | 26 | if (remainder[0] == '-') 27 | { 28 | i++; 29 | sign = -1; 30 | } 31 | 32 | do 33 | { 34 | var t = remainder[i++]; 35 | 36 | if (t == ' ') 37 | { 38 | break; 39 | } 40 | 41 | result = 10 * result + t - '0'; 42 | } 43 | while (i < remainder.Length); 44 | 45 | result *= sign; 46 | 47 | sequence.Add(result); 48 | 49 | remainder = remainder[i..]; 50 | } 51 | while (remainder.Length > 0); 52 | 53 | part2 += sequence[0]; 54 | part1 += sequence[^1]; 55 | var mul = -1; 56 | 57 | var length = sequence.Count; 58 | 59 | while (true) 60 | { 61 | for (var s = 0; s < length - 1; s++) 62 | { 63 | sequence[s] = sequence[s + 1] - sequence[s]; 64 | } 65 | 66 | length -= 1; 67 | var start = sequence[0]; 68 | var end = sequence[length - 1]; 69 | 70 | if (start == 0 && end == 0) 71 | { 72 | break; 73 | } 74 | 75 | part1 += end; 76 | part2 += start * mul; 77 | mul *= -1; 78 | } 79 | 80 | sequence.Clear(); 81 | } 82 | 83 | return new(part1.ToString(), part2.ToString()); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /2023/Answers/Solver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace AdventOfCode; 5 | 6 | public partial class Solver 7 | { 8 | public static int AvailableDays => Answers.Length - 1; 9 | 10 | private static partial IAnswer CreateSolutionInstance(int day); 11 | 12 | public static Solution Solve(int day, string data) 13 | { 14 | var solution = CreateSolutionInstance(day); 15 | return solution.Solve(data); 16 | } 17 | 18 | public static (string, string, string, string) SolveExample(int day) 19 | { 20 | var daySolver = CreateSolutionInstance(day); 21 | 22 | var stopWatch = new Stopwatch(); 23 | stopWatch.Start(); 24 | var solution = daySolver.Solve(DataExamples[day]); 25 | stopWatch.Stop(); 26 | 27 | Console.Write("Example solution: "); 28 | Console.ForegroundColor = ConsoleColor.DarkBlue; 29 | Console.Write(solution.Part1); 30 | Console.ForegroundColor = ConsoleColor.DarkGray; 31 | Console.Write(" | "); 32 | Console.ForegroundColor = ConsoleColor.DarkBlue; 33 | Console.Write(solution.Part2); 34 | Console.ForegroundColor = ConsoleColor.DarkGray; 35 | Console.WriteLine($" ({stopWatch.Elapsed})"); 36 | Console.ResetColor(); 37 | 38 | var correctSolution = AnswersExample[day]; 39 | 40 | if (correctSolution.Part1 != solution.Part1) 41 | { 42 | Console.ForegroundColor = ConsoleColor.Yellow; 43 | Console.Write("Part 1 example answer is wrong, expected: "); 44 | Console.WriteLine(correctSolution.Part1); 45 | Console.ResetColor(); 46 | } 47 | 48 | if (correctSolution.Part2 != solution.Part2) 49 | { 50 | Console.ForegroundColor = ConsoleColor.Yellow; 51 | Console.Write("Part 2 example answer is wrong, expected: "); 52 | Console.WriteLine(correctSolution.Part2); 53 | Console.ResetColor(); 54 | } 55 | 56 | return (correctSolution.Part1, solution.Part1, correctSolution.Part2, solution.Part2); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /2023/Answers/Types/ReadOnlyGrid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace AdventOfCode; 5 | 6 | public readonly struct ReadOnlyGrid 7 | { 8 | private readonly char OutOfBoundsCharacter; 9 | private readonly int Stride; 10 | 11 | public readonly string Data { get; } 12 | public readonly int Width { get; } 13 | public readonly int Height { get; } 14 | 15 | public ReadOnlyGrid(string data, char oob = '\0') 16 | { 17 | OutOfBoundsCharacter = oob; 18 | Data = data; 19 | Width = data.IndexOf('\n'); 20 | Stride = Width + 1; 21 | Height = (data.Length + 1) / Stride; 22 | } 23 | 24 | public readonly char this[int row, int column] 25 | { 26 | get 27 | { 28 | if (row < 0 || column < 0 || row >= Height || column >= Width) 29 | { 30 | return OutOfBoundsCharacter; 31 | } 32 | 33 | return Data[row * Stride + column]; 34 | } 35 | } 36 | 37 | public readonly char this[(int row, int column) d] => this[d.row, d.column]; 38 | 39 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 40 | public (int Row, int Column) IndexOf(char c) => Math.DivRem(Data.IndexOf(c), Stride); 41 | 42 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 43 | public char InfiniteAt(int row, int column) 44 | { 45 | var r = row % Height; 46 | row = r < 0 ? r + Height : r; 47 | 48 | r = column % Width; 49 | column = r < 0 ? r + Width : r; 50 | 51 | return Data[row * Stride + column]; 52 | } 53 | 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | public char InfiniteAt((int row, int column) d) => InfiniteAt(d.row, d.column); 56 | } 57 | -------------------------------------------------------------------------------- /2023/DataExamples/answers.txt: -------------------------------------------------------------------------------- 1 | 220 | 279 2 | 8 | 2286 3 | 4361 | 467835 4 | 13 | 30 5 | 35 | 46 6 | 288 | 71503 7 | 6440 | 5905 8 | 6 | 6 9 | 114 | 2 10 | 80 | 10 11 | 374 | 82000210 12 | 21 | 525152 13 | 405 | 400 14 | 136 | 64 15 | 1320 | 145 16 | 46 | 51 17 | 102 | 94 18 | 62 | 952408144115 19 | 19114 | 167409079868000 20 | 16 | 1 21 | 2665 | 474664087262544 22 | 5 | 7 23 | 94 | 154 24 | 2 | 47 25 | 54 | 0 26 | -------------------------------------------------------------------------------- /2023/DataExamples/day1.txt: -------------------------------------------------------------------------------- 1 | two1nine 2 | eightwothree1 3 | abcone2threexyz 4 | xtwone3four 5 | 4nineeightseven2 6 | zoneight234 7 | 7pqrstsixteen 8 | -------------------------------------------------------------------------------- /2023/DataExamples/day10.txt: -------------------------------------------------------------------------------- 1 | FF7FSF7F7F7F7F7F---7 2 | L|LJ||||||||||||F--J 3 | FL-7LJLJ||||||LJL-77 4 | F--JF--7||LJLJ7F7FJ- 5 | L---JF-JLJ.||-FJLJJ7 6 | |F|F-JF---7F7-L7L|7| 7 | |FFJF7L7F-JF7|JL---7 8 | 7-L-JL7||F7|L7F-7F7| 9 | L.L7LFJ|||||FJL7||LJ 10 | L7JLJL-JLJLJL--JLJ.L 11 | -------------------------------------------------------------------------------- /2023/DataExamples/day11.txt: -------------------------------------------------------------------------------- 1 | ...#...... 2 | .......#.. 3 | #......... 4 | .......... 5 | ......#... 6 | .#........ 7 | .........# 8 | .......... 9 | .......#.. 10 | #...#..... 11 | -------------------------------------------------------------------------------- /2023/DataExamples/day12.txt: -------------------------------------------------------------------------------- 1 | ???.### 1,1,3 2 | .??..??...?##. 1,1,3 3 | ?#?#?#?#?#?#?#? 1,3,1,6 4 | ????.#...#... 4,1,1 5 | ????.######..#####. 1,6,5 6 | ?###???????? 3,2,1 7 | -------------------------------------------------------------------------------- /2023/DataExamples/day13.txt: -------------------------------------------------------------------------------- 1 | #.##..##. 2 | ..#.##.#. 3 | ##......# 4 | ##......# 5 | ..#.##.#. 6 | ..##..##. 7 | #.#.##.#. 8 | 9 | #...##..# 10 | #....#..# 11 | ..##..### 12 | #####.##. 13 | #####.##. 14 | ..##..### 15 | #....#..# 16 | -------------------------------------------------------------------------------- /2023/DataExamples/day14.txt: -------------------------------------------------------------------------------- 1 | O....#.... 2 | O.OO#....# 3 | .....##... 4 | OO.#O....O 5 | .O.....O#. 6 | O.#..O.#.# 7 | ..O..#O..O 8 | .......O.. 9 | #....###.. 10 | #OO..#.... 11 | -------------------------------------------------------------------------------- /2023/DataExamples/day15.txt: -------------------------------------------------------------------------------- 1 | rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 2 | -------------------------------------------------------------------------------- /2023/DataExamples/day16.txt: -------------------------------------------------------------------------------- 1 | .|...\.... 2 | |.-.\..... 3 | .....|-... 4 | ........|. 5 | .......... 6 | .........\ 7 | ..../.\\.. 8 | .-.-/..|.. 9 | .|....-|.\ 10 | ..//.|.... 11 | -------------------------------------------------------------------------------- /2023/DataExamples/day17.txt: -------------------------------------------------------------------------------- 1 | 2413432311323 2 | 3215453535623 3 | 3255245654254 4 | 3446585845452 5 | 4546657867536 6 | 1438598798454 7 | 4457876987766 8 | 3637877979653 9 | 4654967986887 10 | 4564679986453 11 | 1224686865563 12 | 2546548887735 13 | 4322674655533 14 | -------------------------------------------------------------------------------- /2023/DataExamples/day18.txt: -------------------------------------------------------------------------------- 1 | R 6 (#70c710) 2 | D 5 (#0dc571) 3 | L 2 (#5713f0) 4 | D 2 (#d2c081) 5 | R 2 (#59c680) 6 | D 2 (#411b91) 7 | L 5 (#8ceee2) 8 | U 2 (#caa173) 9 | L 1 (#1b58a2) 10 | U 2 (#caa171) 11 | R 2 (#7807d2) 12 | U 3 (#a77fa3) 13 | L 2 (#015232) 14 | U 2 (#7a21e3) 15 | -------------------------------------------------------------------------------- /2023/DataExamples/day19.txt: -------------------------------------------------------------------------------- 1 | px{a<2006:qkq,m>2090:A,rfg} 2 | pv{a>1716:R,A} 3 | lnx{m>1548:A,A} 4 | rfg{s<537:gd,x>2440:R,A} 5 | qs{s>3448:A,lnx} 6 | qkq{x<1416:A,crn} 7 | crn{x>2662:A,R} 8 | in{s<1351:px,qqz} 9 | qqz{s>2770:qs,m<1801:hdj,R} 10 | gd{a>3333:R,R} 11 | hdj{m>838:A,pv} 12 | 13 | {x=787,m=2655,a=1222,s=2876} 14 | {x=1679,m=44,a=2067,s=496} 15 | {x=2036,m=264,a=79,s=2244} 16 | {x=2461,m=1339,a=466,s=291} 17 | {x=2127,m=1623,a=2188,s=1013} 18 | -------------------------------------------------------------------------------- /2023/DataExamples/day2.txt: -------------------------------------------------------------------------------- 1 | Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green 2 | Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue 3 | Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red 4 | Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red 5 | Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green 6 | -------------------------------------------------------------------------------- /2023/DataExamples/day20.txt: -------------------------------------------------------------------------------- 1 | broadcaster -> a 2 | %a -> inv, con 3 | &inv -> b 4 | %b -> con 5 | &con -> rx 6 | -------------------------------------------------------------------------------- /2023/DataExamples/day21.txt: -------------------------------------------------------------------------------- 1 | ................................. 2 | .....###.#......###.#......###.#. 3 | .###.##..#..###.##..#..###.##..#. 4 | ..#.#...#....#.#...#....#.#...#.. 5 | ....#.#........#.#........#.#.... 6 | .##...####..##...####..##...####. 7 | .##..#...#..##..#...#..##..#...#. 8 | .......##.........##.........##.. 9 | .##.#.####..##.#.####..##.#.####. 10 | .##..##.##..##..##.##..##..##.##. 11 | ................................. 12 | ................................. 13 | .....###.#......###.#......###.#. 14 | .###.##..#..###.##..#..###.##..#. 15 | ..#.#...#....#.#...#....#.#...#.. 16 | ....#.#........#.#........#.#.... 17 | .##...####..##..S####..##...####. 18 | .##..#...#..##..#...#..##..#...#. 19 | .......##.........##.........##.. 20 | .##.#.####..##.#.####..##.#.####. 21 | .##..##.##..##..##.##..##..##.##. 22 | ................................. 23 | ................................. 24 | .....###.#......###.#......###.#. 25 | .###.##..#..###.##..#..###.##..#. 26 | ..#.#...#....#.#...#....#.#...#.. 27 | ....#.#........#.#........#.#.... 28 | .##...####..##...####..##...####. 29 | .##..#...#..##..#...#..##..#...#. 30 | .......##.........##.........##.. 31 | .##.#.####..##.#.####..##.#.####. 32 | .##..##.##..##..##.##..##..##.##. 33 | ................................. 34 | -------------------------------------------------------------------------------- /2023/DataExamples/day22.txt: -------------------------------------------------------------------------------- 1 | 1,0,1~1,2,1 2 | 0,0,2~2,0,2 3 | 0,2,3~2,2,3 4 | 0,0,4~0,2,4 5 | 2,0,5~2,2,5 6 | 0,1,6~2,1,6 7 | 1,1,8~1,1,9 8 | -------------------------------------------------------------------------------- /2023/DataExamples/day23.txt: -------------------------------------------------------------------------------- 1 | #.##################### 2 | #.......#########...### 3 | #######.#########.#.### 4 | ###.....#.>.>.###.#.### 5 | ###v#####.#v#.###.#.### 6 | ###.>...#.#.#.....#...# 7 | ###v###.#.#.#########.# 8 | ###...#.#.#.......#...# 9 | #####.#.#.#######.#.### 10 | #.....#.#.#.......#...# 11 | #.#####.#.#.#########v# 12 | #.#...#...#...###...>.# 13 | #.#.#v#######v###.###v# 14 | #...#.>.#...>.>.#.###.# 15 | #####v#.#.###v#.#.###.# 16 | #.....#...#...#.#.#...# 17 | #.#########.###.#.#.### 18 | #...###...#...#...#.### 19 | ###.###.#.###v#####v### 20 | #...#...#.#.>.>.#.>.### 21 | #.###.###.#.###.#.#v### 22 | #.....###...###...#...# 23 | #####################.# 24 | -------------------------------------------------------------------------------- /2023/DataExamples/day24.txt: -------------------------------------------------------------------------------- 1 | 19, 13, 30 @ -2, 1, -2 2 | 18, 19, 22 @ -1, -1, -2 3 | 20, 25, 34 @ -2, -2, -4 4 | 12, 31, 28 @ -1, -2, -1 5 | 20, 19, 15 @ 1, -5, -3 6 | -------------------------------------------------------------------------------- /2023/DataExamples/day25.txt: -------------------------------------------------------------------------------- 1 | jqt: rhn xhk nvd 2 | rsh: frs pzl lsr 3 | xhk: hfx 4 | cmg: qnr nvd lhk bvb 5 | rhn: xhk bvb hfx 6 | bvb: xhk hfx 7 | pzl: lsr hfx nvd 8 | qnr: nvd 9 | ntq: jqt hfx bvb xhk 10 | nvd: lhk 11 | lsr: lhk 12 | rzs: qnr cmg lsr rsh 13 | frs: qnr lhk lsr 14 | -------------------------------------------------------------------------------- /2023/DataExamples/day3.txt: -------------------------------------------------------------------------------- 1 | 467..114.. 2 | ...*...... 3 | ..35..633. 4 | ......#... 5 | 617*...... 6 | .....+.58. 7 | ..592..... 8 | ......755. 9 | ...$.*.... 10 | .664.598.. 11 | -------------------------------------------------------------------------------- /2023/DataExamples/day4.txt: -------------------------------------------------------------------------------- 1 | Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 2 | Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 3 | Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 4 | Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 5 | Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 6 | Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 7 | -------------------------------------------------------------------------------- /2023/DataExamples/day5.txt: -------------------------------------------------------------------------------- 1 | seeds: 79 14 55 13 2 | 3 | seed-to-soil map: 4 | 50 98 2 5 | 52 50 48 6 | 7 | soil-to-fertilizer map: 8 | 0 15 37 9 | 37 52 2 10 | 39 0 15 11 | 12 | fertilizer-to-water map: 13 | 49 53 8 14 | 0 11 42 15 | 42 0 7 16 | 57 7 4 17 | 18 | water-to-light map: 19 | 88 18 7 20 | 18 25 70 21 | 22 | light-to-temperature map: 23 | 45 77 23 24 | 81 45 19 25 | 68 64 13 26 | 27 | temperature-to-humidity map: 28 | 0 69 1 29 | 1 0 69 30 | 31 | humidity-to-location map: 32 | 60 56 37 33 | 56 93 4 34 | -------------------------------------------------------------------------------- /2023/DataExamples/day6.txt: -------------------------------------------------------------------------------- 1 | Time: 7 15 30 2 | Distance: 9 40 200 3 | -------------------------------------------------------------------------------- /2023/DataExamples/day7.txt: -------------------------------------------------------------------------------- 1 | 32T3K 765 2 | T55J5 684 3 | KK677 28 4 | KTJJT 220 5 | QQQJA 483 6 | -------------------------------------------------------------------------------- /2023/DataExamples/day8.txt: -------------------------------------------------------------------------------- 1 | LLR 2 | 3 | AAA = (BBB, BBB) 4 | BBB = (AAA, ZZZ) 5 | ZZZ = (ZZZ, ZZZ) 6 | -------------------------------------------------------------------------------- /2023/DataExamples/day9.txt: -------------------------------------------------------------------------------- 1 | 0 3 6 9 12 15 2 | 1 3 6 10 15 21 3 | 10 13 16 21 30 45 4 | -------------------------------------------------------------------------------- /2023/SolverGenerator/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Generator": { 4 | "commandName": "DebugRoslynComponent", 5 | "targetProject": "..\\Answers\\AdventOfCode.csproj" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /2023/SolverGenerator/SolverGenerator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | true 5 | true 6 | 7 | 8 | 9 | 10 | all 11 | runtime; build; native; contentfiles; analyzers; buildtransitive 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /2023/prep.ps1: -------------------------------------------------------------------------------- 1 | $Day = (Get-Date).Day 2 | $Year = (Get-Date).Year 3 | $Cookie = (Get-Content -Path .\.cookie).Trim() 4 | 5 | New-Item -Path "Data" -Name "day$Day.txt" -ItemType "file" 6 | New-Item -Path "DataExamples" -Name "day$Day.txt" -ItemType "file" 7 | Add-Content -Path "Data\answers.txt" -Value "0 | 0" 8 | Add-Content -Path "DataExamples\answers.txt" -Value "0 | 0" 9 | 10 | $Path = "Answers\Solutions\Day$Day.cs" 11 | 12 | if ((Test-Path $Path) -eq $False) { 13 | ((Get-Content "Answers\Solutions\Day0.cs" -Raw) -replace [regex]::escape("[Answer(0)]"),"[Answer($Day)]" -replace "class Day0","class Day$Day") | Set-Content -NoNewline -Path $Path 14 | } 15 | 16 | $wc = New-Object System.Net.WebClient 17 | $wc.Headers.Add([System.Net.HttpRequestHeader]::Cookie, "session=$Cookie") 18 | $wc.DownloadFile("https://adventofcode.com/$Year/day/$Day/input", (Resolve-Path "Data\day$Day.txt")) 19 | 20 | Start-Process "https://adventofcode.com/$Year/day/$Day" 21 | -------------------------------------------------------------------------------- /2024/AdventOfCode.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33103.184 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "Answers\AdventOfCode.csproj", "{D9537297-BC8C-4803-B23A-6D4FD42B2B95}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SolverGenerator", "SolverGenerator\SolverGenerator.csproj", "{F845D75F-AB5F-4AE1-A095-00548F5123FB}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {D9537297-BC8C-4803-B23A-6D4FD42B2B95}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {F845D75F-AB5F-4AE1-A095-00548F5123FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {F845D75F-AB5F-4AE1-A095-00548F5123FB}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {F845D75F-AB5F-4AE1-A095-00548F5123FB}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {F845D75F-AB5F-4AE1-A095-00548F5123FB}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {C10091A0-1CB1-49F4-A48B-9457CEFA4857} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /2024/Answers/AdventOfCode.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net9.0 5 | AdventOfCode 6 | enable 7 | false 8 | CA1822 9 | true 10 | true 11 | true 12 | true 13 | true 14 | $(DefineConstants);NO_BENCHMARK 15 | x64 16 | win-x64 17 | 18 | 19 | 20 | Data\%(Filename)%(Extension) 21 | 22 | 23 | DataExamples\%(Filename)%(Extension) 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /2024/Answers/AnswerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode; 4 | 5 | [AttributeUsage(AttributeTargets.Class)] 6 | class AnswerAttribute : Attribute 7 | { 8 | public int Day { get; init; } 9 | public bool Slow { get; init; } 10 | public AnswerAttribute(int day) => Day = day; 11 | public AnswerAttribute(int day, bool slow) 12 | { 13 | Day = day; 14 | Slow = slow; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /2024/Answers/BenchmarkSolver.cs: -------------------------------------------------------------------------------- 1 | #if !NO_BENCHMARK 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace AdventOfCode; 5 | 6 | [MemoryDiagnoser] 7 | public class BenchmarkSolver 8 | { 9 | //[Params(1)] 10 | public int Day { get; set; } 11 | 12 | private string Data = string.Empty; 13 | 14 | [GlobalSetup] 15 | public void Setup() 16 | { 17 | Day = System.DateTime.Today.Day; 18 | Data = Solver.Data[Day]; 19 | } 20 | 21 | [Benchmark] 22 | public Solution Solve() 23 | { 24 | return Solver.Solve(Day, Data); 25 | } 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /2024/Answers/IAnswer.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode; 2 | 3 | public interface IAnswer 4 | { 5 | public Solution Solve(string input); 6 | } 7 | -------------------------------------------------------------------------------- /2024/Answers/Solution.cs: -------------------------------------------------------------------------------- 1 | namespace AdventOfCode; 2 | 3 | public record Solution(string Part1, string Part2); 4 | -------------------------------------------------------------------------------- /2024/Answers/Solutions/Day0.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AdventOfCode; 4 | 5 | [Answer(0)] 6 | public class Day0 : IAnswer 7 | { 8 | public Solution Solve(string input) 9 | { 10 | var part1 = 0; 11 | var part2 = 0; 12 | 13 | return new(part1.ToString(), part2.ToString()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2024/Answers/Solutions/Day1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(1)] 7 | public class Day1 : IAnswer 8 | { 9 | public Solution Solve(string input) 10 | { 11 | var part1 = 0; 12 | var part2 = 0; 13 | 14 | var listA = new List(); 15 | var listB = new List(); 16 | var occurrences = new Dictionary(); 17 | 18 | foreach (var line in input.AsSpan().EnumerateLines()) 19 | { 20 | var numLength = (line.Length - 3) / 2; 21 | var a = ParseInt(line[..numLength]); 22 | var b = ParseInt(line[(numLength + 3)..]); 23 | 24 | listA.Add(a); 25 | listB.Add(b); 26 | 27 | if (occurrences.TryGetValue(b, out var count)) 28 | { 29 | occurrences[b] = count + 1; 30 | } 31 | else 32 | { 33 | occurrences[b] = 1; 34 | } 35 | } 36 | 37 | listA.Sort(); 38 | listB.Sort(); 39 | 40 | for (var i = 0; i < listA.Count; i++) 41 | { 42 | var a = listA[i]; 43 | 44 | part1 += Math.Abs(listB[i] - a); 45 | 46 | if (occurrences.TryGetValue(a, out var count)) 47 | { 48 | part2 += a * count; 49 | } 50 | } 51 | 52 | return new(part1.ToString(), part2.ToString()); 53 | } 54 | 55 | static int ParseInt(ReadOnlySpan line) 56 | { 57 | var result = 0; 58 | var i = 0; 59 | 60 | do 61 | { 62 | result = 10 * result + line[i++] - '0'; 63 | } 64 | while (i < line.Length); 65 | 66 | return result; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /2024/Answers/Solutions/Day10.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(10)] 7 | public class Day10 : IAnswer 8 | { 9 | public Solution Solve(string input) 10 | { 11 | var part1 = 0; 12 | var part2 = 0; 13 | var grid = new ReadOnlyGrid(input); 14 | var visited = new HashSet(128); 15 | 16 | for (var y = 0; y < grid.Height; y++) 17 | { 18 | for (var x = 0; x < grid.Width; x++) 19 | { 20 | var c = grid[y, x]; 21 | 22 | if (c != '0') 23 | { 24 | continue; 25 | } 26 | 27 | visited.Clear(); 28 | var (a, b) = FollowTrail(grid, 0, x, y, c, visited); 29 | part1 += a; 30 | part2 += b; 31 | } 32 | } 33 | 34 | return new(part1.ToString(), part2.ToString()); 35 | } 36 | 37 | (int Part1, int Part2) FollowTrail(ReadOnlyGrid grid, int currentScore, int x, int y, char current, HashSet visited) 38 | { 39 | var p1 = 0; 40 | var p2 = 0; 41 | 42 | foreach (var (dx, dy) in Coord.Directions) 43 | { 44 | var xx = x + dx; 45 | var yy = y + dy; 46 | var c = grid[yy, xx]; 47 | 48 | if (c - current != 1) 49 | { 50 | continue; 51 | } 52 | 53 | if (c == '9') 54 | { 55 | p1 += visited.Add(xx * 10000 + yy) ? 1 : 0; 56 | p2 += 1; 57 | continue; 58 | } 59 | 60 | var (a, b) = FollowTrail(grid, currentScore + 1, xx, yy, c, visited); 61 | p1 += a; 62 | p2 += b; 63 | } 64 | 65 | return (p1, p2); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /2024/Answers/Solutions/Day19.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(19)] 7 | public class Day19 : IAnswer 8 | { 9 | public Solution Solve(string input) 10 | { 11 | var part1 = 0; 12 | var part2 = 0L; 13 | var span = input.AsSpan(); 14 | var nl = span.IndexOf("\n\n"); 15 | var patterns = span[..nl].ToString().Split(", "); 16 | var designs = span[(nl + 2)..].ToString().Split("\n"); 17 | var cache = new Dictionary(); 18 | 19 | foreach (var design in designs) 20 | { 21 | cache.Clear(); 22 | 23 | var count = Simulate(design, 0, patterns, cache); 24 | 25 | if (count > 0) 26 | { 27 | part1++; 28 | part2 += count; 29 | } 30 | } 31 | 32 | return new(part1.ToString(), part2.ToString()); 33 | } 34 | 35 | private long Simulate(string design, int pos, string[] patterns, Dictionary cache) 36 | { 37 | if (pos > design.Length) 38 | { 39 | return 0; 40 | } 41 | 42 | if (pos == design.Length) 43 | { 44 | return 1; 45 | } 46 | 47 | if (cache.TryGetValue(pos, out var count)) 48 | { 49 | return count; 50 | } 51 | 52 | foreach (var pattern in patterns) 53 | { 54 | if (pos + pattern.Length > design.Length) 55 | { 56 | continue; 57 | } 58 | 59 | var designSpan = design.AsSpan(pos, pattern.Length); 60 | var patternSpan = pattern.AsSpan(); 61 | 62 | if (designSpan.SequenceEqual(patternSpan)) 63 | { 64 | count += Simulate(design, pos + pattern.Length, patterns, cache); 65 | } 66 | } 67 | 68 | cache[pos] = count; 69 | 70 | return count; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /2024/Answers/Solutions/Day20.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(20)] 7 | public class Day20 : IAnswer 8 | { 9 | record struct Step(int X, int Y, int Cost); 10 | 11 | public Solution Solve(string input) 12 | { 13 | var part1 = 0; 14 | var part2 = 0; 15 | var grid = new ReadOnlyGrid(input, '#'); 16 | var finish = grid.IndexOf('E'); 17 | var position = grid.IndexOf('S'); 18 | var last = position; 19 | var cost = 1; 20 | var path = new List(1024 * 10) 21 | { 22 | new (position.X, position.Y, 0) 23 | }; 24 | 25 | while (position != finish) 26 | { 27 | foreach (var delta in Coord.Directions) 28 | { 29 | var pos = position + delta; 30 | 31 | if (pos != last && grid[pos] != '#') 32 | { 33 | last = position; 34 | position = pos; 35 | path.Add(new Step(pos.X, pos.Y, cost++)); 36 | break; 37 | } 38 | } 39 | } 40 | 41 | for (var i = 0; i < path.Count; i++) 42 | { 43 | var step = path[i]; 44 | 45 | for (var j = i + 1; j < path.Count; j++) 46 | { 47 | var stepEnd = path[j]; 48 | var distance = Math.Abs(stepEnd.Y - step.Y) + Math.Abs(stepEnd.X - step.X); 49 | 50 | if (distance <= 20 && stepEnd.Cost - step.Cost - distance >= 100) 51 | { 52 | part2++; 53 | 54 | if (distance == 2) 55 | { 56 | part1++; 57 | } 58 | } 59 | } 60 | } 61 | 62 | return new(part1.ToString(), part2.ToString()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /2024/Answers/Solutions/Day22.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace AdventOfCode; 6 | 7 | [Answer(22)] 8 | public class Day22 : IAnswer 9 | { 10 | public Solution Solve(string input) 11 | { 12 | var part1 = 0L; 13 | var sequences = new Dictionary(19 * 19 * 19 * 19); 14 | var seenSequences = new HashSet(1024 * 5); 15 | var prices = new byte[2000]; 16 | var changes = new short[2000]; 17 | 18 | foreach (var line in input.AsSpan().EnumerateLines()) 19 | { 20 | var secret = long.Parse(line); 21 | 22 | var previousValue = (byte)(secret % 10); 23 | 24 | for (var i = 0; i < 2000; i++) 25 | { 26 | secret ^= secret * 64; 27 | secret %= 0x1000000; 28 | 29 | secret ^= secret / 32; 30 | secret %= 0x1000000; 31 | 32 | secret ^= secret * 2048; 33 | secret %= 0x1000000; 34 | 35 | prices[i] = (byte)(secret % 10); 36 | changes[i] = (short)(prices[i] - previousValue); 37 | previousValue = prices[i]; 38 | } 39 | 40 | part1 += secret; 41 | 42 | seenSequences.Clear(); 43 | 44 | for (var i = 1; i < 1997; i++) 45 | { 46 | var hash = 0; 47 | 48 | for (var j = 0; j < 4; j++) 49 | { 50 | hash = hash * 19 + changes[i + j] + 9; 51 | } 52 | 53 | if (seenSequences.Add(hash)) 54 | { 55 | sequences.TryGetValue(hash, out var price); 56 | sequences[hash] = price + prices[i + 3]; 57 | } 58 | } 59 | } 60 | 61 | var part2 = sequences.Values.Max(); 62 | 63 | return new Solution(part1.ToString(), part2.ToString()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /2024/Answers/Solutions/Day25.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | 5 | namespace AdventOfCode; 6 | 7 | [Answer(25)] 8 | public class Day25 : IAnswer 9 | { 10 | public Solution Solve(string input) 11 | { 12 | var part1 = 0; 13 | var part2 = 0; 14 | var span = input.AsSpan(); 15 | var locks = new List(); 16 | var keys = new List(); 17 | 18 | foreach (var schema in span.Split("\n\n")) 19 | { 20 | var grid = new ReadOnlyGrid(span[schema]); 21 | var isLock = grid[0, 0] == '#'; 22 | var heights = new byte[5]; 23 | 24 | Debug.Assert(grid.Width == 5); 25 | Debug.Assert(grid.Height == 7); 26 | 27 | for (var x = 0; x < 5; x++) 28 | { 29 | byte h = 0; 30 | 31 | for (var y = 0; y < 7; y++) 32 | { 33 | if (grid[y, x] == '#') 34 | { 35 | h++; 36 | } 37 | } 38 | 39 | heights[x] = --h; 40 | } 41 | 42 | if (isLock) 43 | { 44 | locks.Add(heights); 45 | } 46 | else 47 | { 48 | keys.Add(heights); 49 | } 50 | } 51 | 52 | foreach (var loc in locks) 53 | { 54 | foreach (var key in keys) 55 | { 56 | var fits = true; 57 | 58 | for (var x = 0; x < 5; x++) 59 | { 60 | if (loc[x] + key[x] >= 6) 61 | { 62 | fits = false; 63 | break; 64 | } 65 | } 66 | 67 | if (fits) 68 | { 69 | part1++; 70 | } 71 | } 72 | } 73 | 74 | return new(part1.ToString(), part2.ToString()); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /2024/Answers/Solutions/Day3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(3)] 7 | public class Day3 : IAnswer 8 | { 9 | public Solution Solve(string input) 10 | { 11 | var part1 = 0; 12 | var part2 = 0; 13 | var doing = true; 14 | var span = input.AsSpan(); 15 | 16 | var instructions = SearchValues.Create([ 17 | "mul(", 18 | "do()", 19 | "don't()" 20 | ], StringComparison.Ordinal); 21 | int match; 22 | 23 | while ((match = span.IndexOfAny(instructions)) != -1) 24 | { 25 | if (span[match] == 'd') 26 | { 27 | doing = span[match + 2] == '('; 28 | match += doing ? "do()".Length : "don't()".Length; 29 | span = span[match..]; 30 | continue; 31 | } 32 | 33 | span = span[(match + 4)..]; 34 | 35 | var a = 0; 36 | var b = 0; 37 | 38 | while (char.IsAsciiDigit(span[0])) 39 | { 40 | a = 10 * a + span[0] - '0'; 41 | span = span[1..]; 42 | } 43 | 44 | if (span[0] != ',') 45 | { 46 | continue; 47 | } 48 | 49 | span = span[1..]; // , 50 | 51 | while (char.IsAsciiDigit(span[0])) 52 | { 53 | b = 10 * b + span[0] - '0'; 54 | span = span[1..]; 55 | } 56 | 57 | if (span[0] != ')') 58 | { 59 | continue; 60 | } 61 | 62 | span = span[1..]; // ) 63 | 64 | part1 += a * b; 65 | 66 | if (doing) 67 | { 68 | part2 += a * b; 69 | } 70 | } 71 | 72 | return new(part1.ToString(), part2.ToString()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /2024/Answers/Solutions/Day8.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AdventOfCode; 5 | 6 | [Answer(8)] 7 | public class Day8 : IAnswer 8 | { 9 | public Solution Solve(string input) 10 | { 11 | var grid = new ReadOnlyGrid(input); 12 | var antennas = new Dictionary>(64); 13 | 14 | for (var y = 0; y < grid.Height; y++) 15 | { 16 | for (var x = 0; x < grid.Width; x++) 17 | { 18 | var c = grid[y, x]; 19 | 20 | if (c == '.') 21 | { 22 | continue; 23 | } 24 | 25 | if (antennas.TryGetValue(c, out var list)) 26 | { 27 | list.Add((x, y)); 28 | } 29 | else 30 | { 31 | antennas.Add(c, [(x, y)]); 32 | } 33 | } 34 | } 35 | 36 | var antinodes1 = new HashSet(512); 37 | var antinodes2 = new HashSet(2048); 38 | 39 | foreach (var list in antennas.Values) 40 | { 41 | for (var i = 0; i < list.Count; i++) 42 | { 43 | var a = list[i]; 44 | 45 | for (var j = 0; j < list.Count; j++) 46 | { 47 | if (i == j) 48 | { 49 | continue; 50 | } 51 | 52 | var (x, y) = list[j]; 53 | antinodes2.Add(x * 10000 + y); 54 | 55 | var dx = x - a.X; 56 | var dy = y - a.Y; 57 | 58 | x += dx; 59 | y += dy; 60 | 61 | if (grid[y, x] == '\0') 62 | { 63 | continue; 64 | } 65 | 66 | antinodes1.Add(x * 10000 + y); 67 | 68 | while (grid[y, x] != '\0') 69 | { 70 | antinodes2.Add(x * 10000 + y); 71 | 72 | x += dx; 73 | y += dy; 74 | } 75 | } 76 | } 77 | } 78 | 79 | var part1 = antinodes1.Count; 80 | var part2 = antinodes2.Count; 81 | 82 | return new(part1.ToString(), part2.ToString()); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /2024/Answers/Solver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace AdventOfCode; 5 | 6 | public partial class Solver 7 | { 8 | public static int AvailableDays => Answers.Length - 1; 9 | 10 | private static partial IAnswer CreateSolutionInstance(int day); 11 | 12 | public static Solution Solve(int day, string data) 13 | { 14 | var solution = CreateSolutionInstance(day); 15 | return solution.Solve(data); 16 | } 17 | 18 | public static (string, string, string, string) SolveExample(int day) 19 | { 20 | var daySolver = CreateSolutionInstance(day); 21 | 22 | var stopWatch = new Stopwatch(); 23 | stopWatch.Start(); 24 | var solution = daySolver.Solve(DataExamples[day]); 25 | stopWatch.Stop(); 26 | 27 | Console.Write("Example solution: "); 28 | Console.ForegroundColor = ConsoleColor.DarkBlue; 29 | Console.Write(solution.Part1); 30 | Console.ForegroundColor = ConsoleColor.DarkGray; 31 | Console.Write(" | "); 32 | Console.ForegroundColor = ConsoleColor.DarkBlue; 33 | Console.Write(solution.Part2); 34 | Console.ForegroundColor = ConsoleColor.DarkGray; 35 | Console.WriteLine($" ({stopWatch.Elapsed})"); 36 | Console.ResetColor(); 37 | 38 | var correctSolution = AnswersExample[day]; 39 | 40 | if (correctSolution.Part1 != solution.Part1) 41 | { 42 | Console.ForegroundColor = ConsoleColor.Yellow; 43 | Console.Write("Part 1 example answer is wrong, expected: "); 44 | Console.WriteLine(correctSolution.Part1); 45 | Console.ResetColor(); 46 | } 47 | 48 | if (correctSolution.Part2 != solution.Part2) 49 | { 50 | Console.ForegroundColor = ConsoleColor.Yellow; 51 | Console.Write("Part 2 example answer is wrong, expected: "); 52 | Console.WriteLine(correctSolution.Part2); 53 | Console.ResetColor(); 54 | } 55 | 56 | return (correctSolution.Part1, solution.Part1, correctSolution.Part2, solution.Part2); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /2024/DataExamples/answers.txt: -------------------------------------------------------------------------------- 1 | 11 | 31 2 | 2 | 4 3 | 161 | 48 4 | 18 | 9 5 | 143 | 123 6 | 41 | 6 7 | 3749 | 11387 8 | 14 | 34 9 | 1928 | 2858 10 | 36 | 81 11 | 55312 | 65601038650482 12 | 1930 | 1206 13 | 480 | 875318608908 14 | 12 | none 15 | 10092 | 9021 16 | 11048 | 64 17 | 5,7,3,0 | 117440 18 | 22 | 6,1 19 | 6 | 16 20 | 0 | 0 21 | 126384 | 154115708116294 22 | 37990510 | 23 23 | 7 | co,de,ka,ta 24 | 2024 | ffh,mjb,tgd,wpb,z02,z03,z05,z06,z07,z08,z10,z11 25 | 3 | 0 26 | -------------------------------------------------------------------------------- /2024/DataExamples/day1.txt: -------------------------------------------------------------------------------- 1 | 3 4 2 | 4 3 3 | 2 5 4 | 1 3 5 | 3 9 6 | 3 3 7 | -------------------------------------------------------------------------------- /2024/DataExamples/day10.txt: -------------------------------------------------------------------------------- 1 | 89010123 2 | 78121874 3 | 87430965 4 | 96549874 5 | 45678903 6 | 32019012 7 | 01329801 8 | 10456732 9 | -------------------------------------------------------------------------------- /2024/DataExamples/day11.txt: -------------------------------------------------------------------------------- 1 | 125 17 2 | -------------------------------------------------------------------------------- /2024/DataExamples/day12.txt: -------------------------------------------------------------------------------- 1 | RRRRIICCFF 2 | RRRRIICCCF 3 | VVRRRCCFFF 4 | VVRCCCJFFF 5 | VVVVCJJCFE 6 | VVIVCCJJEE 7 | VVIIICJJEE 8 | MIIIIIJJEE 9 | MIIISIJEEE 10 | MMMISSJEEE 11 | -------------------------------------------------------------------------------- /2024/DataExamples/day13.txt: -------------------------------------------------------------------------------- 1 | Button A: X+94, Y+34 2 | Button B: X+22, Y+67 3 | Prize: X=8400, Y=5400 4 | 5 | Button A: X+26, Y+66 6 | Button B: X+67, Y+21 7 | Prize: X=12748, Y=12176 8 | 9 | Button A: X+17, Y+86 10 | Button B: X+84, Y+37 11 | Prize: X=7870, Y=6450 12 | 13 | Button A: X+69, Y+23 14 | Button B: X+27, Y+71 15 | Prize: X=18641, Y=10279 16 | -------------------------------------------------------------------------------- /2024/DataExamples/day14.txt: -------------------------------------------------------------------------------- 1 | p=0,4 v=3,-3 2 | p=6,3 v=-1,-3 3 | p=10,3 v=-1,2 4 | p=2,0 v=2,-1 5 | p=0,0 v=1,3 6 | p=3,0 v=-2,-2 7 | p=7,6 v=-1,-3 8 | p=3,0 v=-1,-2 9 | p=9,3 v=2,3 10 | p=7,3 v=-1,2 11 | p=2,4 v=2,-3 12 | p=9,5 v=-3,-3 13 | -------------------------------------------------------------------------------- /2024/DataExamples/day15.txt: -------------------------------------------------------------------------------- 1 | ########## 2 | #..O..O.O# 3 | #......O.# 4 | #.OO..O.O# 5 | #..O@..O.# 6 | #O#..O...# 7 | #O..O..O.# 8 | #.OO.O.OO# 9 | #....O...# 10 | ########## 11 | 12 | ^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^ 13 | vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv< 15 | <>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^ 16 | ^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^>< 17 | ^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^ 19 | <><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<> 20 | ^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<>< 21 | v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^ 22 | -------------------------------------------------------------------------------- /2024/DataExamples/day16.txt: -------------------------------------------------------------------------------- 1 | ################# 2 | #...#...#...#..E# 3 | #.#.#.#.#.#.#.#.# 4 | #.#.#.#...#...#.# 5 | #.#.#.#.###.#.#.# 6 | #...#.#.#.....#.# 7 | #.#.#.#.#.#####.# 8 | #.#...#.#.#.....# 9 | #.#.#####.#.###.# 10 | #.#.#.......#...# 11 | #.#.###.#####.### 12 | #.#.#...#.....#.# 13 | #.#.#.#####.###.# 14 | #.#.#.........#.# 15 | #.#.#.#########.# 16 | #S#.............# 17 | ################# 18 | -------------------------------------------------------------------------------- /2024/DataExamples/day17.txt: -------------------------------------------------------------------------------- 1 | Register A: 2024 2 | Register B: 0 3 | Register C: 0 4 | 5 | Program: 0,3,5,4,3,0 6 | -------------------------------------------------------------------------------- /2024/DataExamples/day18.txt: -------------------------------------------------------------------------------- 1 | 5,4 2 | 4,2 3 | 4,5 4 | 3,0 5 | 2,1 6 | 6,3 7 | 2,4 8 | 1,5 9 | 0,6 10 | 3,3 11 | 2,6 12 | 5,1 13 | 1,2 14 | 5,5 15 | 2,5 16 | 6,5 17 | 1,4 18 | 0,4 19 | 6,4 20 | 1,1 21 | 6,1 22 | 1,0 23 | 0,5 24 | 1,6 25 | 2,0 26 | -------------------------------------------------------------------------------- /2024/DataExamples/day19.txt: -------------------------------------------------------------------------------- 1 | r, wr, b, g, bwu, rb, gb, br 2 | 3 | brwrr 4 | bggr 5 | gbbr 6 | rrbgbr 7 | ubwu 8 | bwurrg 9 | brgr 10 | bbrgwb 11 | -------------------------------------------------------------------------------- /2024/DataExamples/day2.txt: -------------------------------------------------------------------------------- 1 | 7 6 4 2 1 2 | 1 2 7 8 9 3 | 9 7 6 2 1 4 | 1 3 2 4 5 5 | 8 6 4 4 1 6 | 1 3 6 7 9 7 | -------------------------------------------------------------------------------- /2024/DataExamples/day20.txt: -------------------------------------------------------------------------------- 1 | ############### 2 | #...#...#.....# 3 | #.#.#.#.#.###.# 4 | #S#...#.#.#...# 5 | #######.#.#.### 6 | #######.#.#...# 7 | #######.#.###.# 8 | ###..E#...#...# 9 | ###.#######.### 10 | #...###...#...# 11 | #.#####.#.###.# 12 | #.#...#.#.#...# 13 | #.#.#.#.#.#.### 14 | #...#...#...### 15 | ############### 16 | -------------------------------------------------------------------------------- /2024/DataExamples/day21.txt: -------------------------------------------------------------------------------- 1 | 029A 2 | 980A 3 | 179A 4 | 456A 5 | 379A 6 | -------------------------------------------------------------------------------- /2024/DataExamples/day22.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 2024 5 | -------------------------------------------------------------------------------- /2024/DataExamples/day23.txt: -------------------------------------------------------------------------------- 1 | kh-tc 2 | qp-kh 3 | de-cg 4 | ka-co 5 | yn-aq 6 | qp-ub 7 | cg-tb 8 | vc-aq 9 | tb-ka 10 | wh-tc 11 | yn-cg 12 | kh-ub 13 | ta-co 14 | de-co 15 | tc-td 16 | tb-wq 17 | wh-td 18 | ta-ka 19 | td-qp 20 | aq-cg 21 | wq-ub 22 | ub-vc 23 | de-ta 24 | wq-aq 25 | wq-vc 26 | wh-yn 27 | ka-de 28 | kh-ta 29 | co-tc 30 | wh-qp 31 | tb-vc 32 | td-yn 33 | -------------------------------------------------------------------------------- /2024/DataExamples/day24.txt: -------------------------------------------------------------------------------- 1 | x00: 1 2 | x01: 0 3 | x02: 1 4 | x03: 1 5 | x04: 0 6 | y00: 1 7 | y01: 1 8 | y02: 1 9 | y03: 1 10 | y04: 1 11 | 12 | ntg XOR fgs -> mjb 13 | y02 OR x01 -> tnw 14 | kwq OR kpj -> z05 15 | x00 OR x03 -> fst 16 | tgd XOR rvg -> z01 17 | vdt OR tnw -> bfw 18 | bfw AND frj -> z10 19 | ffh OR nrd -> bqk 20 | y00 AND y03 -> djm 21 | y03 OR y00 -> psh 22 | bqk OR frj -> z08 23 | tnw OR fst -> frj 24 | gnj AND tgd -> z11 25 | bfw XOR mjb -> z00 26 | x03 OR x00 -> vdt 27 | gnj AND wpb -> z02 28 | x04 AND y00 -> kjc 29 | djm OR pbm -> qhw 30 | nrd AND vdt -> hwm 31 | kjc AND fst -> rvg 32 | y04 OR y02 -> fgs 33 | y01 AND x02 -> pbm 34 | ntg OR kjc -> kwq 35 | psh XOR fgs -> tgd 36 | qhw XOR tgd -> z09 37 | pbm OR djm -> kpj 38 | x03 XOR y03 -> ffh 39 | x00 XOR y04 -> ntg 40 | bfw OR bqk -> z06 41 | nrd XOR fgs -> wpb 42 | frj XOR qhw -> z04 43 | bqk OR frj -> z07 44 | y03 OR x01 -> nrd 45 | hwm AND bqk -> z03 46 | tgd XOR rvg -> z12 47 | tnw OR pbm -> gnj 48 | -------------------------------------------------------------------------------- /2024/DataExamples/day25.txt: -------------------------------------------------------------------------------- 1 | ##### 2 | .#### 3 | .#### 4 | .#### 5 | .#.#. 6 | .#... 7 | ..... 8 | 9 | ##### 10 | ##.## 11 | .#.## 12 | ...## 13 | ...#. 14 | ...#. 15 | ..... 16 | 17 | ..... 18 | #.... 19 | #.... 20 | #...# 21 | #.#.# 22 | #.### 23 | ##### 24 | 25 | ..... 26 | ..... 27 | #.#.. 28 | ###.. 29 | ###.# 30 | ###.# 31 | ##### 32 | 33 | ..... 34 | ..... 35 | ..... 36 | #.... 37 | #.#.. 38 | #.#.# 39 | ##### 40 | -------------------------------------------------------------------------------- /2024/DataExamples/day3.txt: -------------------------------------------------------------------------------- 1 | xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5)) 2 | -------------------------------------------------------------------------------- /2024/DataExamples/day4.txt: -------------------------------------------------------------------------------- 1 | MMMSXXMASM 2 | MSAMXMSMSA 3 | AMXSXMAAMM 4 | MSAMASMSMX 5 | XMASAMXAMM 6 | XXAMMXXAMA 7 | SMSMSASXSS 8 | SAXAMASAAA 9 | MAMMMXMMMM 10 | MXMXAXMASX 11 | -------------------------------------------------------------------------------- /2024/DataExamples/day5.txt: -------------------------------------------------------------------------------- 1 | 47|53 2 | 97|13 3 | 97|61 4 | 97|47 5 | 75|29 6 | 61|13 7 | 75|53 8 | 29|13 9 | 97|29 10 | 53|29 11 | 61|53 12 | 97|53 13 | 61|29 14 | 47|13 15 | 75|47 16 | 97|75 17 | 47|61 18 | 75|61 19 | 47|29 20 | 75|13 21 | 53|13 22 | 23 | 75,47,61,53,29 24 | 97,61,53,29,13 25 | 75,29,13 26 | 75,97,47,61,53 27 | 61,13,29 28 | 97,13,75,29,47 29 | -------------------------------------------------------------------------------- /2024/DataExamples/day6.txt: -------------------------------------------------------------------------------- 1 | ....#..... 2 | .........# 3 | .......... 4 | ..#....... 5 | .......#.. 6 | .......... 7 | .#..^..... 8 | ........#. 9 | #......... 10 | ......#... 11 | -------------------------------------------------------------------------------- /2024/DataExamples/day7.txt: -------------------------------------------------------------------------------- 1 | 190: 10 19 2 | 3267: 81 40 27 3 | 83: 17 5 4 | 156: 15 6 5 | 7290: 6 8 6 15 6 | 161011: 16 10 13 7 | 192: 17 8 14 8 | 21037: 9 7 18 13 9 | 292: 11 6 16 20 10 | -------------------------------------------------------------------------------- /2024/DataExamples/day8.txt: -------------------------------------------------------------------------------- 1 | ............ 2 | ........0... 3 | .....0...... 4 | .......0.... 5 | ....0....... 6 | ......A..... 7 | ............ 8 | ............ 9 | ........A... 10 | .........A.. 11 | ............ 12 | ............ 13 | -------------------------------------------------------------------------------- /2024/DataExamples/day9.txt: -------------------------------------------------------------------------------- 1 | 2333133121414131402 2 | -------------------------------------------------------------------------------- /2024/SolverGenerator/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Generator": { 4 | "commandName": "DebugRoslynComponent", 5 | "targetProject": "..\\Answers\\AdventOfCode.csproj" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /2024/SolverGenerator/SolverGenerator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | true 5 | true 6 | 7 | 8 | 9 | 10 | all 11 | runtime; build; native; contentfiles; analyzers; buildtransitive 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /2024/prep.ps1: -------------------------------------------------------------------------------- 1 | $Day = (Get-Date).Day 2 | $Year = (Get-Date).Year 3 | $Cookie = (Get-Content -Path .\.cookie).Trim() 4 | 5 | New-Item -Path "Data" -Name "day$Day.txt" -ItemType "file" 6 | New-Item -Path "DataExamples" -Name "day$Day.txt" -ItemType "file" 7 | Add-Content -Path "Data\answers.txt" -Value "0 | 0" 8 | Add-Content -Path "DataExamples\answers.txt" -Value "0 | 0" 9 | 10 | $Path = "Answers\Solutions\Day$Day.cs" 11 | 12 | if ((Test-Path $Path) -eq $False) { 13 | ((Get-Content "Answers\Solutions\Day0.cs" -Raw) -replace [regex]::escape("[Answer(0)]"),"[Answer($Day)]" -replace "class Day0","class Day$Day") | Set-Content -NoNewline -Path $Path 14 | } 15 | 16 | $wc = New-Object System.Net.WebClient 17 | $wc.Headers.Add([System.Net.HttpRequestHeader]::Cookie, "session=$Cookie") 18 | $wc.DownloadFile("https://adventofcode.com/$Year/day/$Day/input", (Resolve-Path "Data\day$Day.txt")) 19 | 20 | Start-Process "https://adventofcode.com/$Year/day/$Day" 21 | 22 | code . 23 | code $Path 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | --------------------------------------------------------------------------------