├── 2015 ├── 10 │ ├── input.txt │ └── solve.js ├── 11 │ ├── input.txt │ └── solve.js ├── 12 │ ├── input.txt │ └── solve.js ├── 13 │ ├── input.txt │ └── solve.js ├── 14 │ ├── input.txt │ └── solve.js ├── 15 │ ├── input.txt │ └── solve.js ├── 16 │ ├── input.txt │ └── solve.js ├── 17 │ ├── input.txt │ └── solve.js ├── 18 │ ├── input.txt │ └── solve.js ├── 19 │ ├── input.txt │ └── solve.js ├── 20 │ ├── input.txt │ └── solve.js ├── 21 │ ├── input.txt │ └── solve.js ├── 22 │ ├── input.txt │ └── solve.js ├── 23 │ ├── input.txt │ └── solve.js ├── 24 │ ├── input.txt │ └── solve.js ├── 25 │ ├── input.txt │ └── solve.js ├── 01 │ ├── input.txt │ └── solve.js ├── 02 │ ├── input.txt │ └── solve.js ├── 03 │ ├── input.txt │ └── solve.js ├── 04 │ ├── input.txt │ └── solve.js ├── 05 │ ├── input.txt │ └── solve.js ├── 06 │ ├── input.txt │ └── solve.js ├── 07 │ ├── input.txt │ └── solve.js ├── 08 │ ├── input.txt │ └── solve.js └── 09 │ ├── input.txt │ └── solve.js ├── 2017 ├── 10 │ ├── input.txt │ └── solve.js ├── 11 │ ├── input.txt │ └── solve.js ├── 12 │ ├── input.txt │ └── solve.js ├── 13 │ ├── input.txt │ └── solve.js ├── 14 │ ├── input.txt │ └── solve.js ├── 15 │ ├── input.txt │ └── solve.js ├── 16 │ ├── input.txt │ └── solve.js ├── 17 │ ├── input.txt │ └── solve.js ├── 18 │ ├── input.txt │ └── solve.js ├── 19 │ ├── input.txt │ └── solve.js ├── 20 │ ├── input.txt │ └── solve.js ├── 21 │ ├── input.txt │ └── solve.js ├── 22 │ ├── input.txt │ └── solve.js ├── 23 │ ├── input.txt │ └── solve.js ├── 24 │ ├── input.txt │ └── solve.js ├── 25 │ ├── input.txt │ └── solve.js ├── 01 │ ├── input.txt │ └── solve.js ├── 02 │ ├── input.txt │ └── solve.js ├── 03 │ ├── input.txt │ └── solve.js ├── 04 │ ├── input.txt │ └── solve.js ├── 05 │ ├── input.txt │ └── solve.js ├── 06 │ ├── input.txt │ └── solve.js ├── 07 │ ├── input.txt │ └── solve.js ├── 08 │ ├── input.txt │ └── solve.js └── 09 │ ├── input.txt │ └── solve.js ├── .eslintrc.js ├── .gitignore ├── .vscode └── launch.json ├── README.md ├── index.js ├── package-lock.json ├── package.json ├── spec ├── 2015 │ └── 10-Spec.js ├── 2017-02-Spec.js ├── 2017-04-Spec.js ├── 2017-05-Spec.js ├── 2017-06-Spec.js ├── 2017-07-Spec.js ├── 2017-09-Spec.js ├── 2017-10-Spec.js ├── 2017-15-Spec.js ├── support │ └── jasmine.json ├── utils │ ├── countSpec.js │ ├── firstRepeatedValueSpec.js │ ├── flatMapSpec.js │ ├── nonRepeatedSpec.js │ ├── reduceSpec.js │ ├── skipSpec.js │ ├── unfoldSpec.js │ └── zipSpec.js └── utilsSpec.js └── utils └── utils.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "eslint:recommended", 3 | "parserOptions": { 4 | "ecmaVersion": 6 5 | }, 6 | "env": { 7 | "browser": false, 8 | "node": true, 9 | "es6": true, 10 | "jasmine": true 11 | }, 12 | "rules": { 13 | "no-console": "off" 14 | } 15 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | { 9 | "type": "node", 10 | "request": "launch", 11 | "name": "Launch Program", 12 | "program": "${workspaceFolder}\\index.js" 13 | }, 14 | { 15 | "type": "node", 16 | "request": "launch", 17 | "name": "Specific day", 18 | "program": "${workspaceFolder}\\index.js", 19 | "args": ["2017", "24"] 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /2015/01/input.txt: -------------------------------------------------------------------------------- 1 | ((((()(()(((((((()))(((()((((()())(())()(((()((((((()((()(()(((()(()((())))()((()()())))))))))()((((((())((()))(((((()(((((((((()()))((()(())()((())((()(()))((()))()))()(((((()(((()()))()())((()((((())()())()((((())()(()(()(((()(())(()(())(((((((())()()(((())(()(()(()(())))(()((((())((()))(((()(()()(((((()()(()(((()(((((())()))()((()(()))()((()((((())((((())(()(((())()()(()()()()()(())((((())((())(()()))()((((())))((((()())()((((())((()())((())(())(((((()((((()(((()((((())(()(((()()))()))((((((()((())()())))(((()(()))(()()(()(((()(()))((()()()())((()()()(((())())()())())())((()))(()(()))(((((()(()(())((()(())(())()((((()())()))((((())(())((())())((((()(((())(())((()()((((()((((((()(())()()(()(()()((((()))(())()())()))(())))(())))())()()(())(()))()((()(()(())()()))(()())))))(()))(()()))(())(((((()(()(()()((())()())))))((())())((())(()(())((()))(())(((()((((((((()()()(()))()()(((()))()((()()(())(())())()(()(())))(((((()(())(())(()))))())()))(()))()(()(((((((()((((())))())())())())()((((((((((((((()()((((((()()()())())()())())())(())(())))())((()())((()(()))))))()))))))))))))))))())((())((())()()))))))(((()((()(()()))((())(()()))()()())))(())))))))(()(((())))())()())))()()(())()))()(()))())((()()))))(()))))()))(()()(())))))))()(((()))))()(()))(())())))))()))((()))((()))())(())))))))))((((())()))()))()))())(())()()(())))())))(()())()))((()()(())))(())((((((()(())((()(((()(()()(())))()))))))()))()(()((()))()(()))(()(((())((((())())(())(()))))))))())))))))())())))))())))))()()(((())()(()))))))))())))))(())()()()))()))()))(()(())()()())())))))))())()(()(()))))()()()))))())(()))))()()))))()())))))(((())()()))(()))))))))))()()))))()()()))))(()())())()()())()(()))))()(()))(())))))))(((((())(())())()()))()()))(())))))()(()))))(())(()()))()())()))()))()))()))))())()()))())())))(()))(()))))))())()(((())()))))))))()))()())))())))())))()))))))))))()()))(()()))))))(())()(()))))())(()))))(()))))(()())))))())())()()))))())()))))))))(()))))()))))))()(()())))))))()))())))())))())))())))))))())(()()))))))(()())())))()())()))))))))))))))())))()(())))()))())()()(())(()()))(())))())()())(()(()(()))))())))))))))))())(()))()))()))))(())()())()())))))))))))()()))))))))))))())())))))(()())))))))))))())(())))()))))))))())())(()))()))(())))()))()()(())()))))))()((((())()))())())))))()))()))))((()())()))))())))(())))))))))))))))))()))))()()())()))()()))))())()))((()())))())))(()))(()())))))))()))()))))(())))))))(())))))())()()(()))())()))()()))))())()()))))())()))())))))))(()))))()())()))))))))(()))())))(()))()))))(())()))())())(())())())))))))((((())))))()))()))()())()(())))()))()))()())(()())()()(()())()))))())())))))(()))()))))())(()()(())))))(())()()((())())))))(())(())))))))())))))))))()(())))))))()())())())()(()))))))))(()))))))))())()()))()(()))))))()))))))())))))))(())))()()(())()())))))(((())))()((())()))())))(()()))())(())())))()(((()())))))()(()()())))()()(()()(()()))())()(()()()))())()()))()())(()))))())))))())))(())()()))))(()))))(())(()))(())))))()()))()))))())()))()()(())())))((()))())()))))))()()))))((()(()))))()()))))))())))))())(()((()())))))))))))()())())))()))(()))))))(()))(())()())))(()))))))))())()()()()))))(()())))))))((())))()))(()))(())(())()())()))))))))(())))())))(()))()()))(()()))(()))())))()(())))())((()((()(())))((())))()))))((((())())()())))(())))()))))))())(()()((())))())()(()())))))(()())()))())))))))((())())))))))(()(()))())()()(()()(((()(((()())))))()))))))()(())(()()((()()(())()()))())()())()))()())())())))))))(((())))))))()()))))))(((())()))(()()))(()()))))(()(()()((((())()())((()()))))(()(())))))()((()()()())()()((()((()()))(()))(((()()()))(((())))()(((())()))))))((()(())())))(()())(((((()(()))(()((()))(()())()))))(()(()))()(()))(())(((())(()()))))()()))(((()))))(()()()()))())))((()()()(())()))()))))()()))()))))))((((((()()()))))())((()()(((()))))(()(())(()()())())())))()(((()()))(())((())))(()))(()()()())((())())())(()))))()))()((()(())()(()()(())(()))(())()))(())(()))))(())(())())(()()(()((()()((())))((()))()((())))(((()()()()((((()))(()()))()()()(((())((())())(()()(()()()))()((())(())()))())(((()()(())))()((()()())()())(()(())())(((())(())())((())(())()(((()()))(())))((())(()())())(())((()()()((((((())))((()(((((())()))()))(())(()()))()))(())()()))(())((()()())()()(()))())()((())))()((()()())((((()())((())())())((()((()))()))((())((()()(()((()()(((())(()()))))((()((())()(((())(()((())())((())(()((((((())())()(()())()(())(((())((((((()(())(()((()()()((()()(()()()())))()()(((((()()))()((((((()))()(()(()(()(((()())((()))())()((()))(())))()))()()))())()()))())((((())(()(()))(((((((())(((()(((((()(((()()((((())(((())())))(()()()(()(()))()))((((((()))((()(((()(())((()((((()((((((())(((((())))(((()(()))))(((()(((())()((())(()((()))(((()()(((())((((()(()(((((()))(((()(((((((()(()()()(()(()(()()())(())(((((()(())())()())(()(()(()))()(()()()())(()()(()((()))()((())())()(()))((())(()))()(()))()(((()(()(()((((((()()()()())()(((((()()(((()()()((()(((((()))((((((((()()()(((((()))))))(()()()(())(()))(()()))))(())()))(((((()(((((()()(()(()())(((()))((((()((()(()(()((()(()((())))()(((()((()))((()))(((((((((()((()((()(())))()((((()((()()))((())(((()(((((()()(()(()()((()(()()()(((((((())())()())))))((((()()(()))()))(()((())()(()(((((((((()()(((()(()())(()((()())((())())((((()(((()(((()((((()((()((((()(()((((((())((((((((((((()()(()()((((((((((((((()((()()))()((((((((((((())((((()(()())((()(()(()))()(((((()()(((()()))()())(())((()(((((()((())(((((()((()(((((()))()()((((())()((((())(((((((((()(())(()(())))())(()((())(((())(())(())())(()(()(())()()((()((())()(((()(((((()(())))()(((()((())))((()()()(((()(((()((()(()(())(()((()())(()(()(((()(((((((((())(()((((()()))(()((((()()()()(((()((((((((()(()()((((((()(()()(()((()((((((((((()()(((((((()())(())))(((()()))(((((()((()()())(()()((((())((()((((()))))(())((()(()()(((()(()(((()((((()(((((()))())())(()((())()))(((()())((())((())((((()((()((((((())(()((((()()))((((((())()(()))((()(((())((((((((((()()(((((()(((((()((()()()((((())))(()))()((()(())()()((()((((((((((()((())(())(((((()(()(()()))((((()((((()()((()(((()(((((((((()(()((()((()))((((((()(((())()()((()(((((((()())))()()(()((()((()()(((()(()()()()((((()((())((((()(((((((((()(((()()(((()(()(((()(((()((())()(()((()(()(()(()))()(((()))(()((((()((())((((())((((((())(()))(()((((())((()(()((((((((()()((((((()(()(()()()(())((()((()()(((()(((((((()()((()(((((((()))(((((()(((()(()()()(()(((()((()()((())(()(((((((((()(()((()((((((()()((())()))(((((()((())()())()(((((((((((()))((((()()()()())(()()(()(()()))()))(()))(()(((()()))())(()(()))()()((())(()())()())()(()))()))(()()(()((((((())((()(((((((((((()(())()((()(()((()((()(()((()((((((((((()()())((())()(())))((())()())()(((((()(()())((((()((()(())(()))(((())()((()))(((((())(()))()()(()))(((())((((()((((()(())))(((((((()))))())()())(())((())()(()()((()(()))()(()()(()()((()())((())((()()))((((()))()()))(()()(())()()(((((()(())((()((((()))()))(()())())(((()()(()()))(())))))(()))((())(((((()((((()))()((((()))()((())(((())))(((()())))((()(()()(( -------------------------------------------------------------------------------- /2015/01/solve.js: -------------------------------------------------------------------------------- 1 | 2 | function solve(input, part) { 3 | var solver = part === 1 ? part1BuiltIn : part2Loop; 4 | return solver(input[0]); 5 | } 6 | 7 | function expected(part) { 8 | return part == 1 ? 74 : 1795; 9 | } 10 | 11 | function part1BuiltIn(input) { 12 | return [...input].reduce((x,y) => x+(y === '(' ? 1 : -1),0); 13 | } 14 | 15 | function part2Loop(input) { 16 | let floor = 0; 17 | for(let step = 0; step < input.length; step++) { 18 | floor += (input[step] === '(' ? 1:-1); 19 | if (floor < 0) { 20 | return step+1; 21 | } 22 | } 23 | } 24 | 25 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/02/input.txt: -------------------------------------------------------------------------------- 1 | 4x23x21 2 | 22x29x19 3 | 11x4x11 4 | 8x10x5 5 | 24x18x16 6 | 11x25x22 7 | 2x13x20 8 | 24x15x14 9 | 14x22x2 10 | 30x7x3 11 | 30x22x25 12 | 29x9x9 13 | 29x29x26 14 | 14x3x16 15 | 1x10x26 16 | 29x2x30 17 | 30x10x25 18 | 10x26x20 19 | 1x2x18 20 | 25x18x5 21 | 21x3x24 22 | 2x5x7 23 | 22x11x21 24 | 11x8x8 25 | 16x18x2 26 | 13x3x8 27 | 1x16x19 28 | 19x16x12 29 | 21x15x1 30 | 29x9x4 31 | 27x10x8 32 | 2x7x27 33 | 2x20x23 34 | 24x11x5 35 | 2x8x27 36 | 10x28x10 37 | 24x11x10 38 | 19x2x12 39 | 27x5x10 40 | 1x14x25 41 | 5x14x30 42 | 15x26x12 43 | 23x20x22 44 | 5x12x1 45 | 9x26x9 46 | 23x25x5 47 | 28x16x19 48 | 17x23x17 49 | 2x27x20 50 | 18x27x13 51 | 16x7x18 52 | 22x7x29 53 | 17x28x6 54 | 9x22x17 55 | 10x5x6 56 | 14x2x12 57 | 25x5x6 58 | 26x9x10 59 | 19x21x6 60 | 19x4x27 61 | 23x16x14 62 | 21x17x29 63 | 24x18x10 64 | 7x19x6 65 | 14x15x10 66 | 9x10x19 67 | 20x18x4 68 | 11x14x8 69 | 30x15x9 70 | 25x12x24 71 | 3x12x5 72 | 12x21x28 73 | 8x23x10 74 | 18x26x8 75 | 17x1x8 76 | 2x29x15 77 | 3x13x28 78 | 23x20x11 79 | 27x25x6 80 | 19x21x3 81 | 30x22x27 82 | 28x24x4 83 | 26x18x21 84 | 11x7x16 85 | 22x27x6 86 | 27x5x26 87 | 4x10x4 88 | 4x2x27 89 | 2x3x26 90 | 26x29x19 91 | 30x26x24 92 | 8x25x12 93 | 16x17x5 94 | 13x2x3 95 | 1x30x22 96 | 20x9x1 97 | 24x26x19 98 | 26x18x1 99 | 18x29x24 100 | 1x6x9 101 | 20x27x2 102 | 3x22x21 103 | 4x16x8 104 | 29x18x16 105 | 7x16x23 106 | 13x8x14 107 | 19x25x10 108 | 23x29x6 109 | 23x21x1 110 | 22x26x10 111 | 14x4x2 112 | 18x29x17 113 | 9x4x18 114 | 7x22x9 115 | 19x5x26 116 | 27x29x19 117 | 7x13x14 118 | 19x10x1 119 | 6x22x3 120 | 12x21x5 121 | 24x20x12 122 | 28x2x11 123 | 16x18x23 124 | 2x13x25 125 | 11x7x17 126 | 27x21x4 127 | 2x10x25 128 | 22x16x17 129 | 23x22x15 130 | 17x13x13 131 | 23x24x26 132 | 27x18x24 133 | 24x7x28 134 | 30x12x15 135 | 14x28x19 136 | 2x15x29 137 | 12x13x5 138 | 17x22x21 139 | 27x10x27 140 | 17x6x25 141 | 22x2x1 142 | 1x10x9 143 | 9x7x2 144 | 30x28x3 145 | 28x11x10 146 | 8x23x15 147 | 23x4x20 148 | 12x5x4 149 | 13x17x14 150 | 28x11x2 151 | 21x11x29 152 | 10x23x22 153 | 27x23x14 154 | 7x15x23 155 | 20x2x13 156 | 8x21x4 157 | 10x20x11 158 | 23x28x11 159 | 21x22x25 160 | 23x11x17 161 | 2x29x10 162 | 28x16x5 163 | 30x26x10 164 | 17x24x16 165 | 26x27x25 166 | 14x13x25 167 | 22x27x5 168 | 24x15x12 169 | 5x21x25 170 | 4x27x1 171 | 25x4x10 172 | 15x13x1 173 | 21x23x7 174 | 8x3x4 175 | 10x5x7 176 | 9x13x30 177 | 2x2x30 178 | 26x4x29 179 | 5x14x14 180 | 2x27x9 181 | 22x16x1 182 | 4x23x5 183 | 13x7x26 184 | 2x12x10 185 | 12x7x22 186 | 26x30x26 187 | 28x16x28 188 | 15x19x11 189 | 4x18x1 190 | 20x14x24 191 | 6x10x22 192 | 9x20x3 193 | 14x9x27 194 | 26x17x9 195 | 10x30x28 196 | 6x3x29 197 | 4x16x28 198 | 8x24x11 199 | 23x10x1 200 | 11x7x7 201 | 29x6x15 202 | 13x25x12 203 | 29x14x3 204 | 26x22x21 205 | 8x3x11 206 | 27x13x25 207 | 27x6x2 208 | 8x11x7 209 | 25x12x9 210 | 24x30x12 211 | 13x1x30 212 | 25x23x16 213 | 9x13x29 214 | 29x26x16 215 | 11x15x9 216 | 11x23x6 217 | 15x27x28 218 | 27x24x21 219 | 6x24x1 220 | 25x25x5 221 | 11x1x26 222 | 21x4x24 223 | 10x5x12 224 | 4x30x13 225 | 24x22x5 226 | 26x7x21 227 | 23x3x17 228 | 22x18x2 229 | 25x1x14 230 | 23x25x30 231 | 8x7x7 232 | 30x19x8 233 | 17x6x15 234 | 2x11x20 235 | 8x3x22 236 | 23x14x26 237 | 8x22x25 238 | 27x1x2 239 | 10x26x2 240 | 28x30x7 241 | 5x30x7 242 | 27x16x30 243 | 28x29x1 244 | 8x25x18 245 | 20x12x29 246 | 9x19x9 247 | 7x25x15 248 | 25x18x18 249 | 11x8x2 250 | 4x20x6 251 | 18x5x20 252 | 2x3x29 253 | 25x26x22 254 | 18x25x26 255 | 9x12x16 256 | 18x7x27 257 | 17x20x9 258 | 6x29x26 259 | 17x7x19 260 | 21x7x5 261 | 29x15x12 262 | 22x4x1 263 | 11x12x11 264 | 26x30x4 265 | 12x24x13 266 | 13x8x3 267 | 26x25x3 268 | 21x26x10 269 | 14x9x26 270 | 20x1x7 271 | 11x12x3 272 | 12x11x4 273 | 11x15x30 274 | 17x6x25 275 | 20x22x3 276 | 1x16x17 277 | 11x5x20 278 | 12x12x7 279 | 2x14x10 280 | 14x27x3 281 | 14x16x18 282 | 21x28x24 283 | 14x20x1 284 | 29x14x1 285 | 10x10x9 286 | 25x23x4 287 | 17x15x14 288 | 9x20x26 289 | 16x2x17 290 | 13x28x25 291 | 16x1x11 292 | 19x16x8 293 | 20x21x2 294 | 27x9x22 295 | 24x18x3 296 | 23x30x6 297 | 4x18x3 298 | 30x15x8 299 | 27x20x19 300 | 28x29x26 301 | 2x21x18 302 | 1x23x30 303 | 1x9x12 304 | 4x11x30 305 | 1x28x4 306 | 17x10x10 307 | 12x14x6 308 | 8x9x24 309 | 8x3x3 310 | 29x8x20 311 | 26x29x2 312 | 29x25x25 313 | 11x17x23 314 | 6x30x21 315 | 13x18x29 316 | 2x10x8 317 | 29x29x27 318 | 27x15x15 319 | 16x17x30 320 | 3x3x22 321 | 21x12x6 322 | 22x1x5 323 | 30x8x20 324 | 6x28x13 325 | 11x2x23 326 | 14x18x27 327 | 6x26x13 328 | 10x24x24 329 | 4x24x6 330 | 20x8x3 331 | 23x11x5 332 | 29x5x24 333 | 14x15x22 334 | 21x17x13 335 | 10x10x8 336 | 1x11x23 337 | 21x19x24 338 | 19x9x13 339 | 21x26x28 340 | 25x11x28 341 | 2x17x1 342 | 18x9x8 343 | 5x21x6 344 | 12x5x2 345 | 23x8x15 346 | 30x16x24 347 | 7x9x27 348 | 16x30x7 349 | 2x21x28 350 | 5x10x6 351 | 8x7x1 352 | 28x13x5 353 | 11x5x14 354 | 26x22x29 355 | 23x15x13 356 | 14x2x16 357 | 22x21x9 358 | 4x20x3 359 | 18x17x19 360 | 12x7x9 361 | 6x12x25 362 | 3x30x27 363 | 8x19x22 364 | 1x9x27 365 | 23x20x12 366 | 14x7x29 367 | 9x12x12 368 | 30x2x6 369 | 15x7x16 370 | 19x13x18 371 | 11x8x13 372 | 16x5x3 373 | 19x26x24 374 | 26x8x21 375 | 21x20x7 376 | 15x1x25 377 | 29x15x21 378 | 22x17x7 379 | 16x17x10 380 | 6x12x24 381 | 8x13x27 382 | 30x25x14 383 | 25x7x10 384 | 15x2x2 385 | 18x15x19 386 | 18x13x24 387 | 19x30x1 388 | 17x1x3 389 | 26x21x15 390 | 10x10x18 391 | 9x16x6 392 | 29x7x30 393 | 11x10x30 394 | 6x11x2 395 | 7x29x23 396 | 13x2x30 397 | 25x27x13 398 | 5x15x21 399 | 4x8x30 400 | 15x27x11 401 | 27x1x6 402 | 2x24x11 403 | 16x20x19 404 | 25x28x20 405 | 6x8x4 406 | 27x16x11 407 | 1x5x27 408 | 12x19x26 409 | 18x24x14 410 | 4x25x17 411 | 24x24x26 412 | 28x3x18 413 | 8x20x28 414 | 22x7x21 415 | 24x5x28 416 | 23x30x29 417 | 25x16x27 418 | 28x10x30 419 | 9x2x4 420 | 30x2x23 421 | 21x9x23 422 | 27x4x26 423 | 2x23x16 424 | 24x26x30 425 | 26x1x30 426 | 10x4x28 427 | 11x29x12 428 | 28x13x30 429 | 24x10x28 430 | 8x12x12 431 | 19x27x11 432 | 11x28x7 433 | 14x6x3 434 | 6x27x5 435 | 6x17x14 436 | 24x24x17 437 | 18x23x14 438 | 17x5x7 439 | 11x4x23 440 | 5x1x17 441 | 26x15x24 442 | 3x9x24 443 | 5x3x15 444 | 5x20x19 445 | 5x21x2 446 | 13x5x30 447 | 19x6x24 448 | 19x17x6 449 | 23x7x13 450 | 28x23x13 451 | 9x1x6 452 | 15x12x16 453 | 21x19x9 454 | 25x5x5 455 | 9x7x9 456 | 6x5x8 457 | 3x11x18 458 | 23x25x11 459 | 25x4x6 460 | 4x27x1 461 | 4x3x3 462 | 30x11x5 463 | 9x17x12 464 | 15x6x24 465 | 10x22x15 466 | 29x27x9 467 | 20x21x11 468 | 18x10x5 469 | 11x2x2 470 | 9x8x8 471 | 1x26x21 472 | 11x11x16 473 | 2x18x30 474 | 29x27x24 475 | 27x8x18 476 | 19x3x17 477 | 30x21x26 478 | 25x13x25 479 | 20x22x1 480 | 10x1x12 481 | 11x17x15 482 | 29x11x30 483 | 17x30x27 484 | 21x22x17 485 | 13x6x22 486 | 22x16x12 487 | 27x18x19 488 | 4x13x6 489 | 27x29x10 490 | 3x23x10 491 | 26x16x24 492 | 18x26x20 493 | 11x28x16 494 | 21x6x15 495 | 9x26x17 496 | 8x15x8 497 | 3x7x10 498 | 2x28x8 499 | 1x2x24 500 | 7x8x9 501 | 19x4x22 502 | 11x20x9 503 | 12x22x16 504 | 26x8x19 505 | 13x28x24 506 | 4x10x16 507 | 12x8x10 508 | 14x24x24 509 | 19x19x28 510 | 29x1x15 511 | 10x5x14 512 | 20x19x23 513 | 10x7x12 514 | 1x7x13 515 | 5x12x13 516 | 25x21x8 517 | 22x28x8 518 | 7x9x4 519 | 3x20x15 520 | 15x27x19 521 | 18x24x12 522 | 16x10x16 523 | 22x19x8 524 | 15x4x3 525 | 9x30x25 526 | 1x1x6 527 | 24x4x25 528 | 13x18x29 529 | 10x2x8 530 | 21x1x17 531 | 29x14x22 532 | 17x29x11 533 | 10x27x16 534 | 25x16x15 535 | 14x2x17 536 | 12x27x3 537 | 14x17x25 538 | 24x4x1 539 | 18x28x18 540 | 9x14x26 541 | 28x24x17 542 | 1x26x12 543 | 2x18x20 544 | 12x19x22 545 | 19x25x20 546 | 5x17x27 547 | 17x29x16 548 | 29x19x11 549 | 16x2x4 550 | 23x24x1 551 | 19x18x3 552 | 28x14x6 553 | 18x5x23 554 | 9x24x12 555 | 15x4x6 556 | 15x7x24 557 | 22x15x8 558 | 22x1x22 559 | 6x4x22 560 | 26x1x30 561 | 8x21x27 562 | 7x1x11 563 | 9x8x18 564 | 20x27x12 565 | 26x23x20 566 | 26x22x30 567 | 24x3x16 568 | 8x24x28 569 | 13x28x5 570 | 4x29x23 571 | 22x5x8 572 | 20x22x3 573 | 9x9x17 574 | 28x3x30 575 | 10x13x10 576 | 10x25x13 577 | 9x20x3 578 | 1x21x25 579 | 24x21x15 580 | 21x5x14 581 | 13x8x20 582 | 29x17x3 583 | 5x17x28 584 | 16x12x7 585 | 23x1x24 586 | 4x24x29 587 | 23x25x14 588 | 8x27x2 589 | 23x11x13 590 | 13x4x5 591 | 24x1x26 592 | 21x1x23 593 | 10x12x12 594 | 21x29x25 595 | 27x25x30 596 | 24x23x4 597 | 1x30x23 598 | 29x28x14 599 | 4x11x30 600 | 9x25x10 601 | 17x11x6 602 | 14x29x30 603 | 23x5x5 604 | 25x18x21 605 | 8x7x1 606 | 27x11x3 607 | 5x10x8 608 | 11x1x11 609 | 16x17x26 610 | 15x22x19 611 | 16x9x6 612 | 18x13x27 613 | 26x4x22 614 | 1x20x21 615 | 6x14x29 616 | 11x7x6 617 | 1x23x7 618 | 12x19x13 619 | 18x21x25 620 | 15x17x20 621 | 23x8x9 622 | 15x9x26 623 | 9x12x9 624 | 12x13x14 625 | 27x26x7 626 | 11x19x22 627 | 16x12x21 628 | 10x30x28 629 | 21x2x7 630 | 12x9x18 631 | 7x17x14 632 | 13x17x17 633 | 3x21x10 634 | 30x9x15 635 | 2x8x15 636 | 15x12x10 637 | 23x26x9 638 | 29x30x10 639 | 30x22x17 640 | 17x26x30 641 | 27x26x20 642 | 17x28x17 643 | 30x12x16 644 | 7x23x15 645 | 30x15x19 646 | 13x19x10 647 | 22x10x4 648 | 17x23x10 649 | 2x28x18 650 | 27x21x28 651 | 24x26x5 652 | 6x23x25 653 | 17x4x16 654 | 14x1x13 655 | 23x21x11 656 | 14x15x30 657 | 26x13x10 658 | 30x19x25 659 | 26x6x26 660 | 9x16x29 661 | 15x2x24 662 | 13x3x20 663 | 23x12x30 664 | 22x23x23 665 | 8x21x2 666 | 18x28x5 667 | 21x27x14 668 | 29x28x23 669 | 12x30x28 670 | 17x16x3 671 | 5x19x11 672 | 28x22x22 673 | 1x4x28 674 | 10x10x14 675 | 18x15x7 676 | 18x11x1 677 | 12x7x16 678 | 10x22x24 679 | 27x25x6 680 | 19x29x25 681 | 10x1x26 682 | 26x27x30 683 | 4x23x19 684 | 24x19x4 685 | 21x11x14 686 | 4x13x27 687 | 9x1x11 688 | 16x20x8 689 | 4x3x11 690 | 1x16x12 691 | 14x6x30 692 | 8x1x10 693 | 11x18x7 694 | 29x28x30 695 | 4x21x8 696 | 3x21x4 697 | 6x1x5 698 | 26x18x3 699 | 28x27x27 700 | 17x3x12 701 | 6x1x22 702 | 23x12x28 703 | 12x13x2 704 | 11x2x13 705 | 7x1x28 706 | 27x6x25 707 | 14x14x3 708 | 14x11x20 709 | 2x27x7 710 | 22x24x23 711 | 7x15x20 712 | 30x6x17 713 | 20x23x25 714 | 18x16x27 715 | 2x9x6 716 | 9x18x19 717 | 20x11x22 718 | 11x16x19 719 | 14x29x23 720 | 14x9x20 721 | 8x10x12 722 | 18x17x6 723 | 28x7x16 724 | 12x19x28 725 | 5x3x16 726 | 1x25x10 727 | 4x14x10 728 | 9x6x3 729 | 15x27x28 730 | 13x26x14 731 | 21x8x25 732 | 29x10x20 733 | 14x26x30 734 | 25x13x28 735 | 1x15x23 736 | 6x20x21 737 | 18x2x1 738 | 22x25x16 739 | 23x25x17 740 | 2x14x21 741 | 14x25x16 742 | 12x17x6 743 | 19x29x15 744 | 25x9x6 745 | 19x17x13 746 | 24x22x5 747 | 19x4x13 748 | 10x18x6 749 | 6x25x6 750 | 23x24x20 751 | 8x22x13 752 | 25x10x29 753 | 5x12x25 754 | 20x5x11 755 | 7x16x29 756 | 29x24x22 757 | 28x20x1 758 | 10x27x10 759 | 6x9x27 760 | 26x15x30 761 | 26x3x19 762 | 20x11x3 763 | 26x1x29 764 | 6x23x4 765 | 6x13x21 766 | 9x23x25 767 | 15x1x10 768 | 29x12x13 769 | 7x8x24 770 | 29x30x27 771 | 3x29x19 772 | 14x16x17 773 | 4x8x27 774 | 26x17x8 775 | 10x27x17 776 | 11x28x17 777 | 17x16x27 778 | 1x8x22 779 | 6x30x16 780 | 7x30x22 781 | 20x12x3 782 | 18x10x2 783 | 20x21x26 784 | 11x1x17 785 | 9x15x15 786 | 19x14x30 787 | 24x22x20 788 | 11x26x23 789 | 14x3x23 790 | 1x28x29 791 | 29x20x4 792 | 1x4x20 793 | 12x26x8 794 | 14x11x14 795 | 14x19x13 796 | 15x13x24 797 | 16x7x26 798 | 11x20x11 799 | 5x24x26 800 | 24x25x7 801 | 21x3x14 802 | 24x29x20 803 | 7x12x1 804 | 16x17x4 805 | 29x16x21 806 | 28x8x17 807 | 11x30x25 808 | 1x26x23 809 | 25x19x28 810 | 30x24x5 811 | 26x29x15 812 | 4x25x23 813 | 14x25x19 814 | 29x10x7 815 | 29x29x28 816 | 19x13x24 817 | 21x28x5 818 | 8x15x24 819 | 1x10x12 820 | 2x26x6 821 | 14x14x4 822 | 10x16x27 823 | 9x17x25 824 | 25x8x7 825 | 1x9x28 826 | 10x8x17 827 | 4x12x1 828 | 17x26x29 829 | 23x12x26 830 | 2x21x22 831 | 18x23x13 832 | 1x14x5 833 | 25x27x26 834 | 4x30x30 835 | 5x13x2 836 | 17x9x6 837 | 28x18x28 838 | 7x30x2 839 | 28x22x17 840 | 14x15x14 841 | 10x14x19 842 | 6x15x22 843 | 27x4x17 844 | 28x21x6 845 | 19x29x26 846 | 6x17x17 847 | 20x13x16 848 | 25x4x1 849 | 2x9x5 850 | 30x3x1 851 | 24x21x2 852 | 14x19x12 853 | 22x5x23 854 | 14x4x21 855 | 10x2x17 856 | 3x14x10 857 | 17x5x3 858 | 22x17x13 859 | 5x19x3 860 | 29x22x6 861 | 12x28x3 862 | 9x21x25 863 | 10x2x14 864 | 13x26x7 865 | 18x23x2 866 | 9x14x17 867 | 21x3x13 868 | 13x23x9 869 | 1x20x4 870 | 11x4x1 871 | 19x5x30 872 | 9x9x29 873 | 26x29x14 874 | 1x4x10 875 | 7x27x30 876 | 8x3x23 877 | 1x27x27 878 | 7x27x27 879 | 1x26x16 880 | 29x16x14 881 | 18x6x12 882 | 24x24x24 883 | 26x2x19 884 | 15x17x4 885 | 11x7x14 886 | 14x19x10 887 | 9x10x1 888 | 14x17x9 889 | 20x19x13 890 | 25x20x8 891 | 24x20x21 892 | 26x30x2 893 | 24x2x10 894 | 28x4x13 895 | 27x17x11 896 | 15x3x8 897 | 11x29x10 898 | 26x15x16 899 | 4x28x22 900 | 7x5x22 901 | 10x28x9 902 | 6x28x13 903 | 10x5x6 904 | 20x12x6 905 | 25x30x30 906 | 17x16x14 907 | 14x20x3 908 | 16x10x8 909 | 9x28x14 910 | 16x12x12 911 | 11x13x25 912 | 21x16x28 913 | 10x3x18 914 | 5x9x20 915 | 17x23x5 916 | 3x13x16 917 | 29x30x17 918 | 2x2x8 919 | 15x8x30 920 | 20x1x16 921 | 23x10x29 922 | 4x5x4 923 | 6x18x12 924 | 26x10x22 925 | 21x10x17 926 | 26x12x29 927 | 7x20x21 928 | 18x9x15 929 | 10x23x20 930 | 20x1x27 931 | 10x10x3 932 | 25x12x23 933 | 30x11x15 934 | 16x22x3 935 | 22x10x11 936 | 15x10x20 937 | 2x20x17 938 | 20x20x1 939 | 24x16x4 940 | 23x27x7 941 | 7x27x22 942 | 24x16x8 943 | 20x11x25 944 | 30x28x11 945 | 21x6x24 946 | 15x2x9 947 | 16x30x24 948 | 21x27x9 949 | 7x19x8 950 | 24x13x28 951 | 12x26x28 952 | 16x21x11 953 | 25x5x13 954 | 23x3x17 955 | 23x1x17 956 | 4x17x18 957 | 17x13x18 958 | 25x12x19 959 | 17x4x19 960 | 4x21x26 961 | 6x28x1 962 | 23x22x15 963 | 6x23x12 964 | 21x17x9 965 | 30x4x23 966 | 2x19x21 967 | 28x24x7 968 | 19x24x14 969 | 13x20x26 970 | 19x24x29 971 | 8x26x3 972 | 16x12x14 973 | 17x4x21 974 | 8x4x20 975 | 13x27x17 976 | 9x21x1 977 | 29x25x6 978 | 7x9x26 979 | 13x25x5 980 | 6x9x21 981 | 12x10x11 982 | 30x28x21 983 | 15x6x2 984 | 8x18x19 985 | 26x20x24 986 | 26x17x14 987 | 27x8x1 988 | 19x19x18 989 | 25x24x27 990 | 14x29x15 991 | 22x26x1 992 | 14x17x9 993 | 2x6x23 994 | 29x7x5 995 | 14x16x19 996 | 14x21x18 997 | 10x15x23 998 | 21x29x14 999 | 20x29x30 1000 | 23x11x5 1001 | -------------------------------------------------------------------------------- /2015/02/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | if (part === 1) { 3 | return measure(input, w => 3 * w[0] * w[1] + 2 * w[0] * w[2] + 2 * w[1] * w[2]); 4 | } 5 | else { 6 | return measure(input, w => 2 * w[0] + 2 * w[1] + w[0] * w[1] * w[2]); 7 | } 8 | } 9 | 10 | function expected(part) { 11 | return part == 1 ? 1598415 : 3812909; 12 | } 13 | 14 | function measure(input, fn) { 15 | return input 16 | .map(s => s.split('x')) 17 | .map(x => x.map(n => parseInt(n))) 18 | .map(w => w.sort((a,b)=>a-b)) 19 | .map(fn) 20 | .reduce((a,b) => a+b); 21 | } 22 | 23 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/03/input.txt: -------------------------------------------------------------------------------- 1 | >^^v^<>v<<>v^^^^^><^<<^vv>>>^<<^>><>>><>v<><>^^<^^^<><>>vv>vv>v<<^>v<>^>vv>><>^v<<<v^>>>vv>v^^^<^^<>>v<^^v<>^<<>^>><^<>>><><>v<<<><><>v><<>^^^^v>>^>^^^v^^^^^v<><^v><<><^v^>v<<>^<>^^v^<>vv>^^<^<>^v<><^><><><<<<>^vv^>^vvvvv><><^v<<^<^^v^<>^>^^^v^>v<><^vv<<^<>v<>^^>^^>v^>^<<<v><^v>^>>v>>>>^v^^>v^>^vv^>vv^^v<<^<^^<>v>vv^v>><>>>v^>^>^^v<>^^vv>v^<v<<>^vvvv><<^<>>^v^>>^v<^<>>v^<>>v<>>v^^^><^>>vvvv>^v<^><<>>^<>^>vv>>^^>v^^^><^<<^^v>v<^<<>v>^^vvv^v^>v^<>^^<>v^v>v>vvv>^^v<>v>>^<>><>v>v^<^v<>>^>><>^vvv^>>vvv<>v>v>^>>v<<>^<>^<>>>^v<<<^<^v>vv^>><<>^v^^^v<>^^vv><>><>>^>v^v<>>^<<^v>^^^<>^v^><>v<vv^>vv<<>>><<^v^<>v>>^^<>^><<^>vv>>^<>>v><^>>^^<>>^<^v><>vv^^^v>vvv>^><<>^^>^<vvv<^<<>^>^vvvv>v>vv^<>>^vv<^^^vv><^vv<<^>^^>v^<>^v<<>v^>^>v<<^vvv<<^^>^<<<<>vv>>^<>^>>>v^^>>vv>^^v<<>>>^^v><<^^><><^<>>><^<><><^<>v>v^<><^^v^>^>^vv^>^^<vv<^vvv<>>^^<^>v^>^>^>>v<<<><^v<<><^v<^^vv>vvvvv<<>^v^v>vv>>>vvv^^<^<^<><>v><^v><^<<<>><<^>v<>^>^v>>^<>v^<^>><<>^^>^^^>^^>>><>^v^v><<<vv>v<>v^v><>>>v^<><^vvv>vv^<^<<^<^^v>^>>>v<^<^v^^<^<^>>>vv>^<<><>^>>v>^<<>><^<>v<>vv^^>^>vvv^v<<^<^^^vvv<^^v^vv^>>v<^>^^v<^<^vv>v<vv>^>vvv>>>^^>v<>^v>v^<^>>v>^^v>>>>v^v<^>v>^v<^^<^<>>^<>v<^v<>><^>vv>^^>>vv^<>>^vv<>vv<><<>>v>vv^><>>^^v^>>v^v^><<<>>^^<^v<<^<>>>>^<^>v^><<^>v<^v<^>>^^<<<<><^<^v^v<>>^v<^<<^^vv>^>>^>^vv^>^v<>>^v^^><>v>vv><^>>vvvvv^v^^<^<>v^^^^<><<>>>^v><^>^><^><<^vv<>>v^<v><>^>>v^<^^><>>><^>>>^^<^>vvvv<>^<<>^>>v<^v>^>v>>>vv>v>>v^^^<^^>^v>^>vv>vvv<>v<^>v>^^>>^v^^^^^v^vv><^<><>^>vv<^>>^vvvv^^^>^^v<<^><^^>^<>^^>^<>>^><<^^>v^v>>^>vvvv>^^v>>vv><<v>^^^v^vvv<^><<^>^<>^><<<<^<>v^>^>><>v^v<^vv^^>vv<vv^vvv<<<<>^vv<^^<>^vv^^>^>^v^vv^>>v^vv^^<v^v^^^^v<^<^>v>^>v>^vv^v^^^<^^^<^^<>^<>>>^<>>^^>v^^v^<<^v><^v>v<^><^>vv^^>v>^<><^^^>vv<<<<<^<>^v^v>^vv^<>v>v<^>vv<<^vv>vv<>>v>>><^<<><^^>^<^>>^>^^<^v>^vv><v<<>>^>v>>v>>v<^<<^<^>>>v>^^^v><^>^^>>v<<>^v>vvv^vv<<<>vvv<<>^>>>v^<^>v^^v<^^v<>>^^>^v^>v<<<<^<>v^><<>>><v>><>>^<<<^<^^>v<>>v<>vv<<^<<><<^>v^^^vv^>vvvv>>v>v^><vv^<<><^>>>^<<<^<^<^>v<>>v>>vv^^><<<<^^^v>><<^>>v<><><<>^><^><^v<>v^>>>v<^><^<>^v><^><^^^><^^v^<<><>>^>v^<^v^vv<><^>vv^>v^vvv^<>>^><^<^<>^<<>^v>^>>^v^vv>>^v<<>^><^>>>v<<^^v>>><><><v^^vv>vv^<^v<>^v>>v^v>v<^^vv><>^v<<>v^<>v^>>v>vvv<^><><^^>^vv^>>v^>^<^^<><>><<>^^^><^v^v><<<><<^v^vv>v>><^>>>v<>v^^>>v<<>v>v<>v^^<>>v<^vv<>^<<>v>vv^^<>>^^^<>^^>^v>v>>>^v^v>^^v^v<^<^^><^<>><<>^>>^>^^><>v<><>><<<>>>>vv>>>^>>^v<^>v^^^v<><<<^<<<>>>>>^>vv<^v^<>^^v>vvv<>>>^v^^^v<<<<>>^^^<>v<^<<<>><>>v<^<>^><><^^^>^^<^^v^>><<^vv>^v>>^v>^^>^v>^vvv<>v^v^^<>vv^>>><>v<^><<<>^v>^v<<<^>^>^>v^v<<>^>>>>>v^>vv<<^v^v<<><^v>>vv<>>>>^vv>v^<>vv>v^vvv<><<^<^^^vv^<>^^^^<^><^<>v^>^>>vvv<<>><^vvv^<<^^<<>>>^<>>>v^^><>><<>>>>>>><>>>v<>>v^<>vv<><^^^^v^<<^<<^^>v<^vvv^v>>v>^>>v>^^><v<>vv<^v^vv><>v^>>v<^^^>^><^><>v>>>vvv>^v^<^^^^^v><>v><>v^v^vvvvv<>vv<<^<^>^^v^<<>^<^><<>v^<<^<>v<<^v>>^v<>^>>^^><>v^<^^>^<<<<>vv>^v^v<^^^><>^^<>>v^v<<^^^^v^<><^^<^^^<^v>^>^vv><<<^vvv>v<>v^vv^>>>v^v<>^v<<>^vv>v>v>v^<^>v^^<^>^^^^vv>^^><^>vv^>>^^v>><<<<^><>v<>^^^><<^>v^>^^<^>>><>>>>>^>^><>v>v^v^^><<>vv^v>v^<^<>^^<^>v>^<><<^<^<^>^>^>^^v^<<^^v^^<^<>><^>v>>^^<>^^^<<<^v<^vv>^<<<vv>>>v><>>><>>v<<<>^v>v<^>><^><>^v^>^v>^v<<><<^<>>v>^><>^>><>><^<^^>^v^^<>v^^^^<^v><>^^<<<><<<<<^^>v^vvvv>v<>>vv<^>^v^>v<^vv^v<<><v^v>^^><><^v><>>><<>^vv<>v>>v<^v>>>vv>v>^vv<<>^^vvvv<>^<^<<>^>><^v>vv^^v<<^^><<>v^^<><>^>^>^>v<^^v^^>v<>vvv<^v<<<^^><^<v<>^>v><>^^<^^^>^v<<><<><>vv>v^<>v^><><v<>v>^<<<>vv>>vvv>^^vv^v^^<^^<>v^^<>v>>^^>^>^>v>><^>><>>^<<>><^>v<<<<<<<^v^v^<><v^>v^vv<<^^vv^>>>>^<>v<^v<>v>v^vv>vv>v>>>>vv^<<<v<<<<^^>^^v^><<^v^>^^vvv^>^<>vvvv^<><>v^^^>vv><><<<^^vvv<>><<^vv^>^<^>^^^<<vv^<^<<>^>^v><^>^^>>>vv^><^^vv><>^vv><<v^>v<^v^>>^^^^>vv>>vv^><^vv^vv<<^>vv>^v^^v^v>>>^vv<>v>^^^^<^>><>^v^^^>v<^^<<^^vvvv<^>><><^>>^><^<>v<><^>v><v<^vvv^^>v>^v^v^<>v>^>>vv>><^^^vv<><><<^vv<<>><^v>v^>vvv^v^<<^>^vv^>v^>v>^<<<<>v>^>^^>^<>^>^><<<^<<^<<^>^v>>>><<<>>>>>>^<^v<^>v<>vv<><>v>>^>>^>vv^^><<^>^^<<^>v<^>>vv>^<>v><^>v>>>>>^v<^<<>vv<<><<>v<^^^^v^^<^^^<^<<^>><>v<<>v>>><>v^vv>^>^>>vv^v<^v>vv^>v^v<^>vv<<^^v><^>>^^vv<^<>>v^^>>^v>>>^>>v>v<>v<^vv><>^<<^>vv>>><><>v^><>v^>v>v><^v<>^v<<^vv^><^^>><^^^<<<^>v>^v>>><^>><^>>>^^^<^>vv<><<^<^^>>^^^v^v^v>v>>><^>>>v>^vv<<^^^<^^vv>v<<>v>><<^>^<^>^v^>v><^<^vv>v>><>^<v^>^>><^^^v^v<><<>vvv<^^><>^>vvv>>>^><<>>>^vvv^v^>v<^<^>>^>v<^>^v<<><<<^>^<^^^>vv<^^^^vv<<>vv>>><^<^<>>>^>^>>^<<<<<^^v>^>^<>vvv^^<^><^>^^v>^vv^><^><^>>>v>^v>^>^v><^>v^>^<><<><>vvvv^>^>>v<>^><^>^>^^v^v>v<>^v^><^>>v>v^><<<^>>^<>^<>>v><>>v^>^>^^<>>v^>^>vv^^vv<>v<>^v>^^><^>vv^<^v^<<^<^<><>>>^v^<<^><^>vvv<^>vv^>v<<<>^<>v><^^<>^<^><>vvvv^v^^^>v<>>><<>vvv<<^^^>v>v>>v<^^v>^><^<><<>v^^^vv<>^>^^vv>^<<^v<^v>>>^>>><^<<>^v>>^>vv<<^v>v^^v^>><<^v<<<<>v>v>v^^<^><>^^<<vv<>>>^>>v<>^<>v>v^v>^>><<^^<^^v><<vvv^vv><>><<<^<<>^<^<>>vvv<>^<>v^v<><>>v^v><<>>>vvv>v<>^>>^><^>vv<<>>v<<^><>v>>^^^>^<<>><^<<>>>><^^>vv<>^<>vvvvv^vv<>>^<<><>^^vvv>>>vv<<^^><^v^^v<>^^>^><^>v^^^^v<^<vv^^>v^vv>v><>>vv>^<^>v^v^^v>^>vv^>v^v>^^v<<^>^^<<>^><^v>>>vv^>^^>vvvv>>v<^^>>>v^<><^<^^vv^^>v^<>^^^>>><^^v>v>^<<>^vvv^>^^^>>v>^v><<><<>v<^<<>^><>^>vv>^^^v<<^v^vvv^^>^vv^<^>^>^^v>v^>^<<><<^>v>>vv^vv>>^<<^<^^<^^>v^^^<^<>^<>>^v<^vvv^^v^<><^>>>>>v><><<<>vv<^v>><<>vvv<><v^^>>^>^v>><><^^v<>><>>v^>^<<<>><><^^<>>v<><^vv<^v>^<<<>^<><^>><<>^>v>^^^v>>^<^^v>^><<><>>^>>^<^v<>^>^>vv>^vvv<^>^<<^^<>^^^^vvv<>^vv^^<^>>><>v^<><^<<^>v^^v<>>^vv<>v^^<>>v^vvvvv<>>><^>vv>v^v^^^><^>^^^^v<><^v<<>v^>v>>vv<<>^vvv>^^vv^><>>^>>^>v><>>^^v>^>^>>>^>v<^v>v>^<^^^^^>>v>v<<^>^^^>><<^><>v<>^^^vv<>^^>><<^^>v>vv>vv>v^>^v>v^^<>>><>v><>vvv^^v>^^>^vvvv^>^<>^vvvv>>><>^<^vv<>^v<^v<>^vvv<<>>>^><^^^<^^v^>v<>v^v><>>>^vvv><^vv>v^<^<^v>>v^^>^vvv^v<^<>>^<>>>^^<><^^vv<>^vv^<>>>>^^<<^^<>vv^^><>^^^^v<><><>vvv>^v^>>vv<<^v<<>>^><^>>>^<^<^^>vv^<<^<>>^^><><^^>v<^v^vv>><^^<<^>>v>v<^^^<^><^^vv>^vv<^v><^<><^^^>>^<><^>>>v^>>>>v<><^^>v<^<^>>^>vv>^^v^v^<<<<^v^><<^<><<<><<<>v>>vv><<^<^<>^^^^<>v<<<vv<>vv^^^>><>vv^><>>^vv<<><^^vv<>v^>>^<<>^v< -------------------------------------------------------------------------------- /2015/03/solve.js: -------------------------------------------------------------------------------- 1 | let { scan } = require("../../utils/utils"); 2 | 3 | function solve(input, part) { 4 | var solver = part === 1 ? part1 : part2; 5 | return solver(input[0]); 6 | } 7 | 8 | function expected(part) { 9 | return part == 1 ? 2592 : 2360; 10 | } 11 | 12 | const lookup = { '>':[1,0], '^':[0,1], '<':[-1,0], 'v':[0,-1] }; 13 | 14 | function part1(input) { 15 | let v = [...scan(input, moveSanta, {x:0,y:0})] 16 | .map(({x,y}) => `${x},${y}`); 17 | return new Set(v).size; 18 | } 19 | 20 | function moveSanta(pos,c) { 21 | let [x,y] = lookup[c]; 22 | return {x:pos.x+x,y:pos.y+y}; 23 | } 24 | 25 | function part2(input) { 26 | let santaPos = {x:0,y:0}; 27 | let roboSantaPos = {x:0,y:0}; 28 | let positions = new Set(); 29 | positions.add(`${santaPos.x},${santaPos.y}`); 30 | for(let n = 0; n < input.length; n+=2) { 31 | santaPos = moveSanta(santaPos,input[n]); 32 | roboSantaPos = moveSanta(roboSantaPos,input[n+1]); 33 | positions.add(`${santaPos.x},${santaPos.y}`); 34 | positions.add(`${roboSantaPos.x},${roboSantaPos.y}`); 35 | } 36 | return positions.size; 37 | } 38 | 39 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/04/input.txt: -------------------------------------------------------------------------------- 1 | iwrupvqb -------------------------------------------------------------------------------- /2015/04/solve.js: -------------------------------------------------------------------------------- 1 | var crypto = require('crypto'); 2 | 3 | function solve(input, part) { 4 | var solver = part === 1 ? part1 : part2; 5 | return solver(input[0]); 6 | } 7 | 8 | function expected(part) { 9 | return part == 1 ? 346386 : 9958218; 10 | } 11 | 12 | function find(key,search) { 13 | for (let n = 0; n < 10000000; n++) { 14 | let inputString = `${key}${n}`; 15 | let hash = crypto.createHash('md5').update(inputString).digest('hex'); 16 | if (hash.startsWith(search)) return n; 17 | } 18 | } 19 | 20 | function part1(input) { 21 | return find(input,"00000"); 22 | } 23 | 24 | function part2(input) { 25 | return find(input,"000000"); 26 | } 27 | 28 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/05/solve.js: -------------------------------------------------------------------------------- 1 | 2 | function solve(input, part) { 3 | var solver = part === 1 ? part1 : part2; 4 | return solver(input); 5 | } 6 | 7 | function expected(part) { 8 | return part == 1 ? 236 : 51; 9 | } 10 | function countNice(input, isNice) { 11 | return input.filter(isNice).length; 12 | } 13 | 14 | function part1(input) { 15 | const hasThreeVowels = /[aeiou].*[aeiou].*[aeiou]/g; 16 | const hasDoubleLetter = /(\w)\1+/g; 17 | const containsNaughtyString = /ab|cd|pq|xy/g; 18 | return countNice(input, s => s.match(hasThreeVowels) && s.match(hasDoubleLetter) && !s.match(containsNaughtyString)); 19 | } 20 | 21 | function part2(input) { 22 | const containsNonOverlappingPair = /(\w{2}).*\1+/; 23 | const containsDuplicateSeparatedByOne = /(\w).\1/; 24 | return countNice(input, s => s.match(containsNonOverlappingPair) && s.match(containsDuplicateSeparatedByOne)); 25 | } 26 | 27 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/06/input.txt: -------------------------------------------------------------------------------- 1 | toggle 461,550 through 564,900 2 | turn off 370,39 through 425,839 3 | turn off 464,858 through 833,915 4 | turn off 812,389 through 865,874 5 | turn on 599,989 through 806,993 6 | turn on 376,415 through 768,548 7 | turn on 606,361 through 892,600 8 | turn off 448,208 through 645,684 9 | toggle 50,472 through 452,788 10 | toggle 205,417 through 703,826 11 | toggle 533,331 through 906,873 12 | toggle 857,493 through 989,970 13 | turn off 631,950 through 894,975 14 | turn off 387,19 through 720,700 15 | turn off 511,843 through 581,945 16 | toggle 514,557 through 662,883 17 | turn off 269,809 through 876,847 18 | turn off 149,517 through 716,777 19 | turn off 994,939 through 998,988 20 | toggle 467,662 through 555,957 21 | turn on 952,417 through 954,845 22 | turn on 565,226 through 944,880 23 | turn on 214,319 through 805,722 24 | toggle 532,276 through 636,847 25 | toggle 619,80 through 689,507 26 | turn on 390,706 through 884,722 27 | toggle 17,634 through 537,766 28 | toggle 706,440 through 834,441 29 | toggle 318,207 through 499,530 30 | toggle 698,185 through 830,343 31 | toggle 566,679 through 744,716 32 | toggle 347,482 through 959,482 33 | toggle 39,799 through 981,872 34 | turn on 583,543 through 846,710 35 | turn off 367,664 through 595,872 36 | turn on 805,439 through 964,995 37 | toggle 209,584 through 513,802 38 | turn off 106,497 through 266,770 39 | turn on 975,2 through 984,623 40 | turn off 316,684 through 369,876 41 | turn off 30,309 through 259,554 42 | turn off 399,680 through 861,942 43 | toggle 227,740 through 850,829 44 | turn on 386,603 through 552,879 45 | turn off 703,795 through 791,963 46 | turn off 573,803 through 996,878 47 | turn off 993,939 through 997,951 48 | turn on 809,221 through 869,723 49 | turn off 38,720 through 682,751 50 | turn off 318,732 through 720,976 51 | toggle 88,459 through 392,654 52 | turn off 865,654 through 911,956 53 | toggle 264,284 through 857,956 54 | turn off 281,776 through 610,797 55 | toggle 492,660 through 647,910 56 | turn off 879,703 through 925,981 57 | turn off 772,414 through 974,518 58 | turn on 694,41 through 755,96 59 | turn on 452,406 through 885,881 60 | turn off 107,905 through 497,910 61 | turn off 647,222 through 910,532 62 | turn on 679,40 through 845,358 63 | turn off 144,205 through 556,362 64 | turn on 871,804 through 962,878 65 | turn on 545,676 through 545,929 66 | turn off 316,716 through 413,941 67 | toggle 488,826 through 755,971 68 | toggle 957,832 through 976,992 69 | toggle 857,770 through 905,964 70 | toggle 319,198 through 787,673 71 | turn on 832,813 through 863,844 72 | turn on 818,296 through 818,681 73 | turn on 71,699 through 91,960 74 | turn off 838,578 through 967,928 75 | toggle 440,856 through 507,942 76 | toggle 121,970 through 151,974 77 | toggle 391,192 through 659,751 78 | turn on 78,210 through 681,419 79 | turn on 324,591 through 593,939 80 | toggle 159,366 through 249,760 81 | turn off 617,167 through 954,601 82 | toggle 484,607 through 733,657 83 | turn on 587,96 through 888,819 84 | turn off 680,984 through 941,991 85 | turn on 800,512 through 968,691 86 | turn off 123,588 through 853,603 87 | turn on 1,862 through 507,912 88 | turn on 699,839 through 973,878 89 | turn off 848,89 through 887,893 90 | toggle 344,353 through 462,403 91 | turn on 780,731 through 841,760 92 | toggle 693,973 through 847,984 93 | toggle 989,936 through 996,958 94 | toggle 168,475 through 206,963 95 | turn on 742,683 through 769,845 96 | toggle 768,116 through 987,396 97 | turn on 190,364 through 617,526 98 | turn off 470,266 through 530,839 99 | toggle 122,497 through 969,645 100 | turn off 492,432 through 827,790 101 | turn on 505,636 through 957,820 102 | turn on 295,476 through 698,958 103 | toggle 63,298 through 202,396 104 | turn on 157,315 through 412,939 105 | turn off 69,789 through 134,837 106 | turn off 678,335 through 896,541 107 | toggle 140,516 through 842,668 108 | turn off 697,585 through 712,668 109 | toggle 507,832 through 578,949 110 | turn on 678,279 through 886,621 111 | toggle 449,744 through 826,910 112 | turn off 835,354 through 921,741 113 | toggle 924,878 through 985,952 114 | turn on 666,503 through 922,905 115 | turn on 947,453 through 961,587 116 | toggle 525,190 through 795,654 117 | turn off 62,320 through 896,362 118 | turn on 21,458 through 972,536 119 | turn on 446,429 through 821,970 120 | toggle 376,423 through 805,455 121 | toggle 494,896 through 715,937 122 | turn on 583,270 through 667,482 123 | turn off 183,468 through 280,548 124 | toggle 623,289 through 750,524 125 | turn on 836,706 through 967,768 126 | turn on 419,569 through 912,908 127 | turn on 428,260 through 660,433 128 | turn off 683,627 through 916,816 129 | turn on 447,973 through 866,980 130 | turn on 688,607 through 938,990 131 | turn on 245,187 through 597,405 132 | turn off 558,843 through 841,942 133 | turn off 325,666 through 713,834 134 | toggle 672,606 through 814,935 135 | turn off 161,812 through 490,954 136 | turn on 950,362 through 985,898 137 | turn on 143,22 through 205,821 138 | turn on 89,762 through 607,790 139 | toggle 234,245 through 827,303 140 | turn on 65,599 through 764,997 141 | turn on 232,466 through 965,695 142 | turn on 739,122 through 975,590 143 | turn off 206,112 through 940,558 144 | toggle 690,365 through 988,552 145 | turn on 907,438 through 977,691 146 | turn off 838,809 through 944,869 147 | turn on 222,12 through 541,832 148 | toggle 337,66 through 669,812 149 | turn on 732,821 through 897,912 150 | toggle 182,862 through 638,996 151 | turn on 955,808 through 983,847 152 | toggle 346,227 through 841,696 153 | turn on 983,270 through 989,756 154 | turn off 874,849 through 876,905 155 | turn off 7,760 through 678,795 156 | toggle 973,977 through 995,983 157 | turn off 911,961 through 914,976 158 | turn on 913,557 through 952,722 159 | turn off 607,933 through 939,999 160 | turn on 226,604 through 517,622 161 | turn off 3,564 through 344,842 162 | toggle 340,578 through 428,610 163 | turn on 248,916 through 687,925 164 | toggle 650,185 through 955,965 165 | toggle 831,359 through 933,536 166 | turn off 544,614 through 896,953 167 | toggle 648,939 through 975,997 168 | turn on 464,269 through 710,521 169 | turn off 643,149 through 791,320 170 | turn off 875,549 through 972,643 171 | turn off 953,969 through 971,972 172 | turn off 236,474 through 772,591 173 | toggle 313,212 through 489,723 174 | toggle 896,829 through 897,837 175 | toggle 544,449 through 995,905 176 | turn off 278,645 through 977,876 177 | turn off 887,947 through 946,977 178 | turn on 342,861 through 725,935 179 | turn on 636,316 through 692,513 180 | toggle 857,470 through 950,528 181 | turn off 736,196 through 826,889 182 | turn on 17,878 through 850,987 183 | turn on 142,968 through 169,987 184 | turn on 46,470 through 912,853 185 | turn on 182,252 through 279,941 186 | toggle 261,143 through 969,657 187 | turn off 69,600 through 518,710 188 | turn on 372,379 through 779,386 189 | toggle 867,391 through 911,601 190 | turn off 174,287 through 900,536 191 | toggle 951,842 through 993,963 192 | turn off 626,733 through 985,827 193 | toggle 622,70 through 666,291 194 | turn off 980,671 through 985,835 195 | turn off 477,63 through 910,72 196 | turn off 779,39 through 940,142 197 | turn on 986,570 through 997,638 198 | toggle 842,805 through 943,985 199 | turn off 890,886 through 976,927 200 | turn off 893,172 through 897,619 201 | turn off 198,780 through 835,826 202 | toggle 202,209 through 219,291 203 | turn off 193,52 through 833,283 204 | toggle 414,427 through 987,972 205 | turn on 375,231 through 668,236 206 | turn off 646,598 through 869,663 207 | toggle 271,462 through 414,650 208 | turn off 679,121 through 845,467 209 | toggle 76,847 through 504,904 210 | turn off 15,617 through 509,810 211 | toggle 248,105 through 312,451 212 | turn off 126,546 through 922,879 213 | turn on 531,831 through 903,872 214 | toggle 602,431 through 892,792 215 | turn off 795,223 through 892,623 216 | toggle 167,721 through 533,929 217 | toggle 813,251 through 998,484 218 | toggle 64,640 through 752,942 219 | turn on 155,955 through 892,985 220 | turn on 251,329 through 996,497 221 | turn off 341,716 through 462,994 222 | toggle 760,127 through 829,189 223 | turn on 86,413 through 408,518 224 | toggle 340,102 through 918,558 225 | turn off 441,642 through 751,889 226 | turn on 785,292 through 845,325 227 | turn off 123,389 through 725,828 228 | turn on 905,73 through 983,270 229 | turn off 807,86 through 879,276 230 | toggle 500,866 through 864,916 231 | turn on 809,366 through 828,534 232 | toggle 219,356 through 720,617 233 | turn off 320,964 through 769,990 234 | turn off 903,167 through 936,631 235 | toggle 300,137 through 333,693 236 | toggle 5,675 through 755,848 237 | turn off 852,235 through 946,783 238 | toggle 355,556 through 941,664 239 | turn on 810,830 through 867,891 240 | turn off 509,869 through 667,903 241 | toggle 769,400 through 873,892 242 | turn on 553,614 through 810,729 243 | turn on 179,873 through 589,962 244 | turn off 466,866 through 768,926 245 | toggle 143,943 through 465,984 246 | toggle 182,380 through 569,552 247 | turn off 735,808 through 917,910 248 | turn on 731,802 through 910,847 249 | turn off 522,74 through 731,485 250 | turn on 444,127 through 566,996 251 | turn off 232,962 through 893,979 252 | turn off 231,492 through 790,976 253 | turn on 874,567 through 943,684 254 | toggle 911,840 through 990,932 255 | toggle 547,895 through 667,935 256 | turn off 93,294 through 648,636 257 | turn off 190,902 through 532,970 258 | turn off 451,530 through 704,613 259 | toggle 936,774 through 937,775 260 | turn off 116,843 through 533,934 261 | turn on 950,906 through 986,993 262 | turn on 910,51 through 945,989 263 | turn on 986,498 through 994,945 264 | turn off 125,324 through 433,704 265 | turn off 60,313 through 75,728 266 | turn on 899,494 through 940,947 267 | toggle 832,316 through 971,817 268 | toggle 994,983 through 998,984 269 | toggle 23,353 through 917,845 270 | toggle 174,799 through 658,859 271 | turn off 490,878 through 534,887 272 | turn off 623,963 through 917,975 273 | toggle 721,333 through 816,975 274 | toggle 589,687 through 890,921 275 | turn on 936,388 through 948,560 276 | turn off 485,17 through 655,610 277 | turn on 435,158 through 689,495 278 | turn on 192,934 through 734,936 279 | turn off 299,723 through 622,847 280 | toggle 484,160 through 812,942 281 | turn off 245,754 through 818,851 282 | turn on 298,419 through 824,634 283 | toggle 868,687 through 969,760 284 | toggle 131,250 through 685,426 285 | turn off 201,954 through 997,983 286 | turn on 353,910 through 832,961 287 | turn off 518,781 through 645,875 288 | turn off 866,97 through 924,784 289 | toggle 836,599 through 857,767 290 | turn on 80,957 through 776,968 291 | toggle 277,130 through 513,244 292 | turn off 62,266 through 854,434 293 | turn on 792,764 through 872,842 294 | turn off 160,949 through 273,989 295 | turn off 664,203 through 694,754 296 | toggle 491,615 through 998,836 297 | turn off 210,146 through 221,482 298 | turn off 209,780 through 572,894 299 | turn on 766,112 through 792,868 300 | turn on 222,12 through 856,241 301 | -------------------------------------------------------------------------------- /2015/06/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | var solver = part === 1 ? part1 : part2; 3 | return solver(input); 4 | } 5 | 6 | function expected(part) { 7 | return part == 1 ? 543903 : 14687245; 8 | } 9 | 10 | let parseInstruction = function(actionSelector, i) { 11 | const pattern = /(turn on|toggle|turn off) (\d+),(\d+) through (\d+),(\d+)/ 12 | const groups = pattern.exec(i); 13 | let action = actionSelector[groups[1]]; 14 | let fromPos = [ parseInt(groups[2]), parseInt(groups[3]) ] 15 | let toPos = [ parseInt(groups[4]), parseInt(groups[5]) ] 16 | return { action, fromPos, toPos }; 17 | } 18 | 19 | let expandPositions = function* ( [x0,y0], [x1,y1]) { 20 | for(let x = x0; x <= x1; x++) { 21 | for(let y = y0; y <= y1; y++) { 22 | yield [x,y]; 23 | } 24 | } 25 | } 26 | 27 | let applyAction = function (acc, action,[x,y]) { 28 | acc[x][y] = action(acc[x][y]); 29 | return acc; 30 | } 31 | 32 | let calculate = function(actionSelector, input) { 33 | let state = [] 34 | for(let x = 0; x < 1000; x++) { 35 | let row = new Array(1000).fill(0); 36 | state.push(row); 37 | } 38 | for (let i of input) { 39 | let ins = parseInstruction(actionSelector, i); 40 | for(let p of expandPositions(ins.fromPos, ins.toPos)) { 41 | applyAction(state, ins.action, p); 42 | } 43 | } 44 | return state.map(r => r.reduce((a,b) => a+b)) 45 | .reduce((a,b) => a+b); 46 | } 47 | 48 | function part1(input) { 49 | const lookup = { 50 | "turn on": () => 1, 51 | "turn off": () => 0, 52 | "toggle": n => n == 1 ? 0 : 1 53 | }; 54 | return calculate (lookup,input); 55 | } 56 | 57 | function part2(input) { 58 | const lookup = { 59 | "turn on": n => n + 1, 60 | "turn off": n => n > 0 ? n - 1 : 0, 61 | "toggle": n => n + 2 62 | }; 63 | return calculate (lookup,input); 64 | } 65 | 66 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/07/input.txt: -------------------------------------------------------------------------------- 1 | NOT dq -> dr 2 | kg OR kf -> kh 3 | ep OR eo -> eq 4 | 44430 -> b 5 | NOT gs -> gt 6 | dd OR do -> dp 7 | eg AND ei -> ej 8 | y AND ae -> ag 9 | jx AND jz -> ka 10 | lf RSHIFT 2 -> lg 11 | z AND aa -> ac 12 | dy AND ej -> el 13 | bj OR bi -> bk 14 | kk RSHIFT 3 -> km 15 | NOT cn -> co 16 | gn AND gp -> gq 17 | cq AND cs -> ct 18 | eo LSHIFT 15 -> es 19 | lg OR lm -> ln 20 | dy OR ej -> ek 21 | NOT di -> dj 22 | 1 AND fi -> fj 23 | kf LSHIFT 15 -> kj 24 | NOT jy -> jz 25 | NOT ft -> fu 26 | fs AND fu -> fv 27 | NOT hr -> hs 28 | ck OR cl -> cm 29 | jp RSHIFT 5 -> js 30 | iv OR jb -> jc 31 | is OR it -> iu 32 | ld OR le -> lf 33 | NOT fc -> fd 34 | NOT dm -> dn 35 | bn OR by -> bz 36 | aj AND al -> am 37 | cd LSHIFT 15 -> ch 38 | jp AND ka -> kc 39 | ci OR ct -> cu 40 | gv AND gx -> gy 41 | de AND dk -> dm 42 | x RSHIFT 5 -> aa 43 | et RSHIFT 2 -> eu 44 | x RSHIFT 1 -> aq 45 | ia OR ig -> ih 46 | bk LSHIFT 1 -> ce 47 | y OR ae -> af 48 | NOT ca -> cb 49 | e AND f -> h 50 | ia AND ig -> ii 51 | ck AND cl -> cn 52 | NOT jh -> ji 53 | z OR aa -> ab 54 | 1 AND en -> eo 55 | ib AND ic -> ie 56 | NOT eh -> ei 57 | iy AND ja -> jb 58 | NOT bb -> bc 59 | ha OR gz -> hb 60 | 1 AND cx -> cy 61 | NOT ax -> ay 62 | ev OR ew -> ex 63 | bn RSHIFT 2 -> bo 64 | er OR es -> et 65 | eu OR fa -> fb 66 | jp OR ka -> kb 67 | ea AND eb -> ed 68 | k AND m -> n 69 | et RSHIFT 3 -> ev 70 | et RSHIFT 5 -> ew 71 | hz RSHIFT 1 -> is 72 | ki OR kj -> kk 73 | NOT h -> i 74 | lv LSHIFT 15 -> lz 75 | as RSHIFT 1 -> bl 76 | hu LSHIFT 15 -> hy 77 | iw AND ix -> iz 78 | lf RSHIFT 1 -> ly 79 | fp OR fv -> fw 80 | 1 AND am -> an 81 | ap LSHIFT 1 -> bj 82 | u LSHIFT 1 -> ao 83 | b RSHIFT 5 -> f 84 | jq AND jw -> jy 85 | iu RSHIFT 3 -> iw 86 | ih AND ij -> ik 87 | NOT iz -> ja 88 | de OR dk -> dl 89 | iu OR jf -> jg 90 | as AND bd -> bf 91 | b RSHIFT 3 -> e 92 | jq OR jw -> jx 93 | iv AND jb -> jd 94 | cg OR ch -> ci 95 | iu AND jf -> jh 96 | lx -> a 97 | 1 AND cc -> cd 98 | ly OR lz -> ma 99 | NOT el -> em 100 | 1 AND bh -> bi 101 | fb AND fd -> fe 102 | lf OR lq -> lr 103 | bn RSHIFT 3 -> bp 104 | bn AND by -> ca 105 | af AND ah -> ai 106 | cf LSHIFT 1 -> cz 107 | dw OR dx -> dy 108 | gj AND gu -> gw 109 | jg AND ji -> jj 110 | jr OR js -> jt 111 | bl OR bm -> bn 112 | gj RSHIFT 2 -> gk 113 | cj OR cp -> cq 114 | gj OR gu -> gv 115 | b OR n -> o 116 | o AND q -> r 117 | bi LSHIFT 15 -> bm 118 | dy RSHIFT 1 -> er 119 | cu AND cw -> cx 120 | iw OR ix -> iy 121 | hc OR hd -> he 122 | 0 -> c 123 | db OR dc -> dd 124 | kk RSHIFT 2 -> kl 125 | eq LSHIFT 1 -> fk 126 | dz OR ef -> eg 127 | NOT ed -> ee 128 | lw OR lv -> lx 129 | fw AND fy -> fz 130 | dz AND ef -> eh 131 | jp RSHIFT 3 -> jr 132 | lg AND lm -> lo 133 | ci RSHIFT 2 -> cj 134 | be AND bg -> bh 135 | lc LSHIFT 1 -> lw 136 | hm AND ho -> hp 137 | jr AND js -> ju 138 | 1 AND io -> ip 139 | cm AND co -> cp 140 | ib OR ic -> id 141 | NOT bf -> bg 142 | fo RSHIFT 5 -> fr 143 | ip LSHIFT 15 -> it 144 | jt AND jv -> jw 145 | jc AND je -> jf 146 | du OR dt -> dv 147 | NOT fx -> fy 148 | aw AND ay -> az 149 | ge LSHIFT 15 -> gi 150 | NOT ak -> al 151 | fm OR fn -> fo 152 | ff AND fh -> fi 153 | ci RSHIFT 5 -> cl 154 | cz OR cy -> da 155 | NOT ey -> ez 156 | NOT ju -> jv 157 | NOT ls -> lt 158 | kk AND kv -> kx 159 | NOT ii -> ij 160 | kl AND kr -> kt 161 | jk LSHIFT 15 -> jo 162 | e OR f -> g 163 | NOT bs -> bt 164 | hi AND hk -> hl 165 | hz OR ik -> il 166 | ek AND em -> en 167 | ao OR an -> ap 168 | dv LSHIFT 1 -> ep 169 | an LSHIFT 15 -> ar 170 | fo RSHIFT 1 -> gh 171 | NOT im -> in 172 | kk RSHIFT 1 -> ld 173 | hw LSHIFT 1 -> iq 174 | ec AND ee -> ef 175 | hb LSHIFT 1 -> hv 176 | kb AND kd -> ke 177 | x AND ai -> ak 178 | dd AND do -> dq 179 | aq OR ar -> as 180 | iq OR ip -> ir 181 | dl AND dn -> do 182 | iu RSHIFT 5 -> ix 183 | as OR bd -> be 184 | NOT go -> gp 185 | fk OR fj -> fl 186 | jm LSHIFT 1 -> kg 187 | NOT cv -> cw 188 | dp AND dr -> ds 189 | dt LSHIFT 15 -> dx 190 | et RSHIFT 1 -> fm 191 | dy RSHIFT 3 -> ea 192 | fp AND fv -> fx 193 | NOT p -> q 194 | dd RSHIFT 2 -> de 195 | eu AND fa -> fc 196 | ba AND bc -> bd 197 | dh AND dj -> dk 198 | lr AND lt -> lu 199 | he RSHIFT 1 -> hx 200 | ex AND ez -> fa 201 | df OR dg -> dh 202 | fj LSHIFT 15 -> fn 203 | NOT kx -> ky 204 | gk OR gq -> gr 205 | dy RSHIFT 2 -> dz 206 | gh OR gi -> gj 207 | lj AND ll -> lm 208 | x OR ai -> aj 209 | bz AND cb -> cc 210 | 1 AND lu -> lv 211 | as RSHIFT 3 -> au 212 | ce OR cd -> cf 213 | il AND in -> io 214 | dd RSHIFT 1 -> dw 215 | NOT lo -> lp 216 | c LSHIFT 1 -> t 217 | dd RSHIFT 3 -> df 218 | dd RSHIFT 5 -> dg 219 | lh AND li -> lk 220 | lf RSHIFT 5 -> li 221 | dy RSHIFT 5 -> eb 222 | NOT kt -> ku 223 | at OR az -> ba 224 | x RSHIFT 3 -> z 225 | NOT lk -> ll 226 | lb OR la -> lc 227 | 1 AND r -> s 228 | lh OR li -> lj 229 | ln AND lp -> lq 230 | kk RSHIFT 5 -> kn 231 | ea OR eb -> ec 232 | ci AND ct -> cv 233 | b RSHIFT 2 -> d 234 | jp RSHIFT 1 -> ki 235 | NOT cr -> cs 236 | NOT jd -> je 237 | jp RSHIFT 2 -> jq 238 | jn OR jo -> jp 239 | lf RSHIFT 3 -> lh 240 | 1 AND ds -> dt 241 | lf AND lq -> ls 242 | la LSHIFT 15 -> le 243 | NOT fg -> fh 244 | at AND az -> bb 245 | au AND av -> ax 246 | kw AND ky -> kz 247 | v OR w -> x 248 | kk OR kv -> kw 249 | ks AND ku -> kv 250 | kh LSHIFT 1 -> lb 251 | 1 AND kz -> la 252 | NOT kc -> kd 253 | x RSHIFT 2 -> y 254 | et OR fe -> ff 255 | et AND fe -> fg 256 | NOT ac -> ad 257 | jl OR jk -> jm 258 | 1 AND jj -> jk 259 | bn RSHIFT 1 -> cg 260 | NOT kp -> kq 261 | ci RSHIFT 3 -> ck 262 | ev AND ew -> ey 263 | 1 AND ke -> kf 264 | cj AND cp -> cr 265 | ir LSHIFT 1 -> jl 266 | NOT gw -> gx 267 | as RSHIFT 2 -> at 268 | iu RSHIFT 1 -> jn 269 | cy LSHIFT 15 -> dc 270 | hg OR hh -> hi 271 | ci RSHIFT 1 -> db 272 | au OR av -> aw 273 | km AND kn -> kp 274 | gj RSHIFT 1 -> hc 275 | iu RSHIFT 2 -> iv 276 | ab AND ad -> ae 277 | da LSHIFT 1 -> du 278 | NOT bw -> bx 279 | km OR kn -> ko 280 | ko AND kq -> kr 281 | bv AND bx -> by 282 | kl OR kr -> ks 283 | 1 AND ht -> hu 284 | df AND dg -> di 285 | NOT ag -> ah 286 | d OR j -> k 287 | d AND j -> l 288 | b AND n -> p 289 | gf OR ge -> gg 290 | gg LSHIFT 1 -> ha 291 | bn RSHIFT 5 -> bq 292 | bo OR bu -> bv 293 | 1 AND gy -> gz 294 | s LSHIFT 15 -> w 295 | NOT ie -> if 296 | as RSHIFT 5 -> av 297 | bo AND bu -> bw 298 | hz AND ik -> im 299 | bp AND bq -> bs 300 | b RSHIFT 1 -> v 301 | NOT l -> m 302 | bp OR bq -> br 303 | g AND i -> j 304 | br AND bt -> bu 305 | t OR s -> u 306 | hz RSHIFT 5 -> ic 307 | gk AND gq -> gs 308 | fl LSHIFT 1 -> gf 309 | he RSHIFT 3 -> hg 310 | gz LSHIFT 15 -> hd 311 | hf OR hl -> hm 312 | 1 AND gd -> ge 313 | fo OR fz -> ga 314 | id AND if -> ig 315 | fo AND fz -> gb 316 | gr AND gt -> gu 317 | he OR hp -> hq 318 | fq AND fr -> ft 319 | ga AND gc -> gd 320 | fo RSHIFT 2 -> fp 321 | gl OR gm -> gn 322 | hg AND hh -> hj 323 | NOT hn -> ho 324 | gl AND gm -> go 325 | he RSHIFT 5 -> hh 326 | NOT gb -> gc 327 | hq AND hs -> ht 328 | hz RSHIFT 3 -> ib 329 | hz RSHIFT 2 -> ia 330 | fq OR fr -> fs 331 | hx OR hy -> hz 332 | he AND hp -> hr 333 | gj RSHIFT 5 -> gm 334 | hf AND hl -> hn 335 | hv OR hu -> hw 336 | NOT hj -> hk 337 | gj RSHIFT 3 -> gl 338 | fo RSHIFT 3 -> fq 339 | he RSHIFT 2 -> hf 340 | -------------------------------------------------------------------------------- /2015/07/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | var solver = part === 1 ? part1 : part2; 3 | return solver(input); 4 | } 5 | 6 | function expected(part) { 7 | return part == 1 ? 3176 : 14710; 8 | } 9 | 10 | let state = {}; 11 | 12 | let isLetter = c => c >= 'a' && c <= 'z'; 13 | 14 | 15 | let getVal = function(x) { 16 | if (isLetter(x[0])) { 17 | if (x in state) return state[x]; 18 | throw new Error("oops"); 19 | } 20 | return parseInt(x); 21 | } 22 | 23 | let assign = x => getVal(x[0]); 24 | let and = x => (getVal(x[0]) & getVal(x[2])) & 0xFFFF; 25 | let or = x => (getVal(x[0]) | getVal(x[2])) & 0xFFFF; 26 | let lshift = x => (getVal(x[0]) << getVal(x[2])) & 0xFFFF; 27 | let rshift = x => (getVal(x[0]) >> getVal(x[2])) & 0xFFFF; 28 | let not = x => (~getVal(x[1])) & 0xFFFF; 29 | 30 | function selector(p) { 31 | if (p[1] === "->") return assign; 32 | else if (p[1] === "AND") return and; 33 | else if (p[1] === "OR") return or; 34 | else if (p[1] === "LSHIFT") return lshift; 35 | else if (p[1] === "RSHIFT") return rshift; 36 | else if (p[0] === "NOT") return not; 37 | throw new Error(`unknown selector ${p}`); 38 | } 39 | 40 | function getInstructions(input) { 41 | return input.map(i => i.split(' ')).map(i => ({ target:i[i.length-1], action:selector(i), params:i })); 42 | } 43 | 44 | function runInstructions(ins) { 45 | var i; 46 | 47 | while ((i = ins.shift()) !== undefined) { 48 | try { 49 | state[i.target] = i.action(i.params); 50 | } 51 | catch(ex) { 52 | if (ex.message === "oops") { 53 | ins.push(i); 54 | } 55 | else { 56 | throw ex; 57 | } 58 | } 59 | } 60 | return state["a"]; 61 | } 62 | 63 | function part1(input) { 64 | state={}; 65 | return runInstructions(getInstructions(input)); 66 | } 67 | 68 | function part2(input) { 69 | state={}; 70 | var ins = getInstructions(input); 71 | ins = ins.map(i => i.target === "b" ? { target:"b", action:assign, params:["3176","->","b"]} : i) 72 | return runInstructions(ins); 73 | } 74 | 75 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/08/input.txt: -------------------------------------------------------------------------------- 1 | "sjdivfriyaaqa\xd2v\"k\"mpcu\"yyu\"en" 2 | "vcqc" 3 | "zbcwgmbpijcxu\"yins\"sfxn" 4 | "yumngprx" 5 | "bbdj" 6 | "czbggabkzo\"wsnw\"voklp\"s" 7 | "acwt" 8 | "aqttwnsohbzian\"evtllfxwkog\"cunzw" 9 | "ugvsgfv" 10 | "xlnillibxg" 11 | "kexh\"pmi" 12 | "syvugow" 13 | "m\"ktqnw" 14 | "yrbajyndte\\rm" 15 | "f\"kak\x70sn\xc4kjri" 16 | "yxthr" 17 | "alvumfsjni\"kohg" 18 | "trajs\x5brom\xf1yoijaumkem\"\"tahlzs" 19 | "\"oedr\"pwdbnnrc" 20 | "qsmzhnx\"" 21 | "\"msoytqimx\\tbklqz" 22 | "mjdfcgwdshrehgs" 23 | "\"rivyxahf\"" 24 | "ciagc\x04bp" 25 | "xkfc" 26 | "xrgcripdu\x4c\xc4gszjhrvumvz\"mngbirb" 27 | "gvmae\"yiiujoqvr\"mkxmgbbut\"u" 28 | "ih" 29 | "ncrqlejehs" 30 | "mkno\x43pcfdukmemycp" 31 | "uanzoqxkpsksbvdnkji\"feamp" 32 | "axoufpnbx\\ao\x61pfj\"b" 33 | "dz\\ztawzdjy" 34 | "ihne\"enumvswypgf" 35 | "\"dgazthrphbshdo\\vuqoiy\"" 36 | "dlnmptzt\\zahwpylc\\b\"gmslrqysk" 37 | "mhxznyzcp" 38 | "rebr\"amvxw\x5fmbnfpkkeghlntavj" 39 | "lades\x47ncgdof\"\"jmbbk" 40 | "dwxuis\xa5wdkx\\z\"admgnoddpgkt\\zs" 41 | "g\\k\x27qsl\x34hwfglcdxqbeclt\xca\\" 42 | "lhyjky\\m\"pvnm\\xmynpxnlhndmahjl" 43 | "c\"uxabbgorrpprw\"xas\\vefkxioqpt" 44 | "rfrvjxpevcmma\x71gtfipo" 45 | "fgh\"kcwoqwfnjgdlzfclprg\"q" 46 | "onxnwykrba" 47 | "hkkg\x60f\"tjzsanpvarzgkfipl" 48 | "\"aintes\"ofq\"juiaqlqxmvpe\\a" 49 | "wiyczzs\"ciwk" 50 | "mfqeu" 51 | "v\xe1z\x7ftzalmvdmncfivrax\\rjwq" 52 | "k\"vtg" 53 | "exhrtdugeml\xf0" 54 | "behnchkpld" 55 | "mhgxy\"mfcrg\xc5gnp\"\"osqhj" 56 | "rlvjy" 57 | "awe" 58 | "ctwy" 59 | "vt" 60 | "\x54t" 61 | "zugfmmfomz" 62 | "cv\"cvcvfaada\x04fsuqjinbfh\xa9cq\xd2c\"d" 63 | "oj" 64 | "xazanf\"wbmcrn" 65 | "\\\\zkisyjpbzandqikqjqvee" 66 | "dpsnbzdwnxk\\v" 67 | "sj\"tuupr\\oyoh" 68 | "myvkgnw\x81q\xaaokt\\emgejbsyvxcl\\\xee" 69 | "ejeuqvunjcirdkkpt\"nlns" 70 | "twmlvwxyvfyqqzu" 71 | "\"xwtzdp\x98qkcis\"dm\\\"ep\"xyykq" 72 | "vvcq\\expok" 73 | "wgukjfanjgpdjb" 74 | "\"mjcjajnxy\\dcpc" 75 | "wdvgnecw\\ab\x44klceduzgsvu" 76 | "dqtqkukr\"iacngufbqkdpxlwjjt" 77 | "\"xj\"\x66qofsqzkoah" 78 | "nptiwwsqdep" 79 | "gsnlxql\x30mjl" 80 | "yeezwokjwrhelny\"" 81 | "bjauamn\\izpmzqqasid" 82 | "tvjdbkn\"tiziw\x82r" 83 | "w" 84 | "xwoakbbnjnypnaa\xa9wft\"slrmoqkl" 85 | "vwxtnlvaaasyruykgygrvpiopzygf\"vq" 86 | "qdancvnvmhlmpj\\isdxs" 87 | "xzc\\elw" 88 | "b\"wxeqvy\"qf\"g\xcaoklsucwicyw\"dovr" 89 | "yomlvvjdbngz\"rly\"afr" 90 | "bfb\"x\"aweuwbwmoa\x13\"t\"zhr" 91 | "\"dmfoxb\"qvpjzzhykt\xd2\"\"ryhxi" 92 | "psqef\"yu\\qiflie\"\x79w" 93 | "arzewkej\"lqmh\\sayyusxxo\\" 94 | "vuvvp" 95 | "hc\"lg\x6bcpupsewzklai\"l" 96 | "cjdfygc\"auorqybnuqghsh\x10" 97 | "j" 98 | "wqjexk\"eyq\\lbroqhk\\dqzsqk" 99 | "dws\"ru\"dvxfiwapif\"oqwzmle" 100 | "agcykg\\jt\\vzklqjvknoe" 101 | "kksd\"jmslja\\z\"y\\b\xaagpyojct" 102 | "nnpipxufvbfpoz\"jno" 103 | "dtw" 104 | "xlolvtahvgqkx\\dgnhj\\spsclpcxv\\" 105 | "mxea\\mbjpi" 106 | "lgbotkk\"zmxh\\\\qji\"jszulnjsxkqf" 107 | "lwckmhwhx\"gmftlb\x91am" 108 | "xxdxqyxth" 109 | "\"lmqhwkjxmvayxy" 110 | "tf" 111 | "qy" 112 | "wdqmwxdztax\"m\"\x09\x11xdxmfwxmtqgwvf" 113 | "\xcbnazlf\"ghziknszmsrahaf" 114 | "e\x6aupmzhxlvwympgjjpdvo\"kylfa" 115 | "\x81vhtlillb\xactgoatva" 116 | "dvnlgr" 117 | "f" 118 | "xg\xfacwizsadgeclm" 119 | "vnnrzbtw\"\\prod\\djbyppngwayy\"" 120 | "lrt\xf4jahwvfz" 121 | "aqpnjtom\"ymkak\\dadfybqrso\\fwv" 122 | "gz\"aac\"mrbk\"ktommrojraqh" 123 | "wycamwoecsftepfnlcdkm" 124 | "nrhddblbuzlqsl\x9cben" 125 | "vckxhyqkmqmdseazcykrbysm" 126 | "sil\xbbtevmt\"gvrvybui\"faw\"j" 127 | "cjex\\tp\x45pzf" 128 | "asjobvtxszfodgf\"ibftg" 129 | "gkyjyjdrxdcllnh\"sjcibenrdnxv" 130 | "oswsdpjyxpbwnqbcpl\"yrdvs\\zq" 131 | "\"\"tyowzc\\fycbp\"jbwrbvgui" 132 | "cbpcabqkdgzmpgcwjtrchxp" 133 | "iyrzfh\x45gw\"fdlfpiaap\x31xqq" 134 | "evgksznidz" 135 | "b\\w\\" 136 | "loufizbiy\x57aim\"bgk" 137 | "qjfyk" 138 | "g\"anmloghvgr\x07zwqougqhdz" 139 | "usbbmwcxd\\bdgg" 140 | "htitqcpczml" 141 | "eke\\cqvpexqqk\"to\"tqmljrpn\xe6lji\"" 142 | "g\xd2ifdsej" 143 | "h\"sk\"haajajpagtcqnzrfqn\xe6btzo" 144 | "wfkuffdxlvm\\cvlyzlbyunclhmpp" 145 | "myaavh\"spue" 146 | "hqvez\x68d\"eo\"eaioh" 147 | "s\"qd\"oyxxcglcdnuhk" 148 | "ilqvar" 149 | "srh" 150 | "puuifxrfmpc\"bvalwi\x2blu\\" 151 | "yywlbutufzysbncw\\nqsfbhpz\"mngjq" 152 | "zbl\\jfcuop" 153 | "hjdouiragzvxsqkreup\\" 154 | "qi" 155 | "ckx\\funlj\xa7ahi" 156 | "k" 157 | "ufrcnh\"ajteit" 158 | "cqv\"bgjozjj\x60x\xa8yhvmdvutchjotyuz" 159 | "hkuiet\"oku\x8cfhumfpasl" 160 | "\"\\sbe\x4d" 161 | "vhknazqt" 162 | "eyyizvzcahgflvmoowvs\\jhvygci" 163 | "kki\x3ewcefkgtjap\"xtpxh\"lzepoqj" 164 | "wvtk" 165 | "\"ynet" 166 | "zh\\obk\"otagx\x59txfzf" 167 | "ocowhxlx\xe6zqg\x63wx\\tclkhq\\vmaze" 168 | "w\"cf" 169 | "qpniprnrzrnvykghqnalr" 170 | "jctcqra\"\x05dhlydpqamorqjsijt\\xjdgt" 171 | "sig" 172 | "qhlbidbflwxe\"xljbwls\x20vht" 173 | "irmrebfla\xefsg\"j" 174 | "nep" 175 | "hjuvsqlizeqobepf" 176 | "guzbcdp\"obyh" 177 | "\"mjagins\xf9tqykaxy\"" 178 | "knvsdnmtr\"zervsb" 179 | "hzuy" 180 | "zza\"k\"buapb\\elm\xfeya" 181 | "lrqar\"dfqwkaaqifig\"uixjsz" 182 | "\"azuo\x40rmnlhhluwsbbdb\x32pk\\yu\"pbcf" 183 | "dplkdyty" 184 | "rfoyciebwlwphcycmguc" 185 | "ivnmmiemhgytmlprq\\eh" 186 | "lhkyzaaothfdhmbpsqd\\yyw" 187 | "tnlzifupcjcaj" 188 | "\\qiyirsdrfpmu\\\x15xusifaag" 189 | "\\lcomf\\s" 190 | "uramjivcirjhqcqcg" 191 | "kkbaklbxfxikffnuhtu\xc6t\"d" 192 | "n\xefai" 193 | "\"toy\"bnbpevuzoc\"muywq\"gz\"grbm" 194 | "\"muu\\wt" 195 | "\\srby\"ee" 196 | "erf\"gvw\"swfppf" 197 | "pbqcgtn\"iuianhcdazfvmidn\\nslhxdf" 198 | "uxbp" 199 | "up\\mgrcyaegiwmjufn" 200 | "nulscgcewj\\dvoyvhetdegzhs\"" 201 | "masv\"k\\rzrb" 202 | "qtx\x79d\"xdxmbxrvhj" 203 | "fid\\otpkgjlh\"qgsvexrckqtn\xf4" 204 | "tagzu" 205 | "bvl\\\"noseec" 206 | "\\xgicuuh" 207 | "w\"a\"npemf" 208 | "sxp" 209 | "nsmpktic\x8awxftscdcvijjobnq\"gjd" 210 | "uks\"\"jxvyvfezz\"aynxoev\"cuoav" 211 | "m" 212 | "lkvokj" 213 | "vkfam\"yllr\"q\x92o\x4ebecnvhshhqe\\" 214 | "efdxcjkjverw" 215 | "lmqzadwhfdgmep\x02tzfcbgrbfekhat" 216 | "cpbk\x9azqegbpluczssouop\x36ztpuoxsw" 217 | "cqwoczxdd\"erdjka" 218 | "cwvqnjgbw\\fxdlby" 219 | "mvtm" 220 | "lt\"bbqzpumplkg" 221 | "ntd\xeeuwweucnuuslqfzfq" 222 | "y\xabl\"dbebxjrlbmuoo\\\x1au" 223 | "qjoqx\\a" 224 | "pu\"ekdnfpmly\xbago\"" 225 | "fjhhdy" 226 | "arl" 227 | "xcywisim\"bwuwf\"\"raepeawwjub" 228 | "pbe" 229 | "dbnqfpzyaumxtqnd\xc5dcqrkwyop" 230 | "ojv\x40vtkwgkqepm\x8bzft\\vedrry" 231 | "wggqkfbwqumsgajqwphjec\"mstxpwz" 232 | "zjkbem" 233 | "icpfqxbelxazlls" 234 | "pvpqs\\abcmtyielugfgcv\"tjxapxqxnx" 235 | "oqddwlvmtv\"\x39lyybylfb\"jmngnpjrdw" 236 | "gisgbve" 237 | "\"aglg" 238 | "y\"\"ss\xafvhxlrjv" 239 | "qbgqjsra" 240 | "ihshbjgqpdcljpmdwdprwloy" 241 | "djja\\wcdn\"svkrgpqn\"uz\"hc\x43hj" 242 | "cbjm" 243 | "pnn" 244 | "pqvh\"noh" 245 | "\"\\fdktlp" 246 | "ncea" 247 | "pqgzphiyy" 248 | "\xbedovhxuipaohlcvkwtxwmpz\"ckaif\"r" 249 | "arjuzbjowqciunfwgxtph\"vlhy\"n" 250 | "c" 251 | "nrpdxunulgudqzlhtae" 252 | "iefheu\"uru\"" 253 | "aqijysxuijud\"np\\opbichhudil\xbesum" 254 | "pfpevmtstl\"lde\"bzr\"vspdxs" 255 | "vparfbdjwvzsocpnzhp" 256 | "g\x4ffxaarafrsjthq\\\xc1rw" 257 | "ng\\rqx\\gwpzucbh\xafl" 258 | "rw\"nf\\dna" 259 | "jkkeahxurxla\\g\xb3czrlsyimmwcwthr" 260 | "twaailoypu\"oas\"kpuuyedlaw\\\xb0vzt" 261 | "hznex\\gdiqvtugi" 262 | "imdibsunjeswhk" 263 | "ta\\icileuzpxro\"cfmv\"mzp" 264 | "coykr\x57luiysucfaflmilhlehmvzeiepo" 265 | "u\x3dfh\xd4yt" 266 | "piw\x1bz\"eowy\"vfk\"wqiekw" 267 | "gan\"y" 268 | "p\"bevidoazcznr\"hddxuuq\"" 269 | "bwzucczznutbxe" 270 | "z\"viqgyqjisior\\iecosmjbknol" 271 | "dmlpcglcfkfsctxydjvayhymv\x3c\\gp" 272 | "bfvkqrintbbvgfv" 273 | "xlzntrgdck\"cprc\xadczyarbznqmuhxyuh" 274 | "uqdxnuwioc\"kdytxq\\ig" 275 | "xrafmucpmfi" 276 | "vr\"hltmfrge" 277 | "eonf\"nt\\wtcnsocs" 278 | "j\xb7xoslyjeyjksplkqixncgkylkw" 279 | "njw\"pefgfbez\x9axshdmplxzquqe" 280 | "di\x58bvptfsafirpc" 281 | "l\x1fkco" 282 | "x" 283 | "mprndo\"n" 284 | "psegit" 285 | "svbdnkkuuqs\"sqxu\"oqcyz\"aizashk" 286 | "cwkljukxer\\\"\\nff\"esjwiyaoy" 287 | "ilxrkgbjjxpvhdtq\"cpiuoofdnkpp" 288 | "hlngi\"ulxep\\qohtmqnqjb\"rkgerho" 289 | "gxws\"bcgm\"p" 290 | "bv\"mds\\zhfusiepgrz\\b\x32fscdzz" 291 | "l\xfampwtme\x69qvxnx\"\"\xc4jruuymjxrpsv" 292 | "qqmxhrn" 293 | "xziq\\\x18ybyv\x9am\"neacoqjzytertisysza" 294 | "aqcbvlvcrzceeyx\\j\"\"x" 295 | "yjuhhb" 296 | "\x5em\"squulpy" 297 | "dpbntplgmwb" 298 | "utsgfkm\\vbftjknlktpthoeo" 299 | "ccxjgiocmuhf\"ycnh" 300 | "lltj\"kbbxi" 301 | -------------------------------------------------------------------------------- /2015/08/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | var solver = part === 1 ? part1 : part2; 3 | return solver(input); 4 | } 5 | 6 | let expected = part => part === 1 ? 1333 : 2046; 7 | 8 | let [q,bq,bb] = ["\"","\\\"","\\\\"]; 9 | 10 | let unescape = s => s.slice(1,-1).replace(/\\"/g, q).replace(/\\\\/g, "?").replace(/\\x[0-9a-f]{2}/g,"?"); 11 | let escape = s => q + s.replace(/\\/g, bb).replace(/"/g, bq) + q; 12 | 13 | let sumDiffLengths = (strings,f) => strings.map(f).reduce((acc,[a,b]) => acc + (a.length - b.length), 0); 14 | let part1 = input => sumDiffLengths(input, f => [f, unescape(f)]); 15 | let part2 = input => sumDiffLengths(input, f => [escape(f), f]); 16 | 17 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/09/input.txt: -------------------------------------------------------------------------------- 1 | Faerun to Norrath = 129 2 | Faerun to Tristram = 58 3 | Faerun to AlphaCentauri = 13 4 | Faerun to Arbre = 24 5 | Faerun to Snowdin = 60 6 | Faerun to Tambi = 71 7 | Faerun to Straylight = 67 8 | Norrath to Tristram = 142 9 | Norrath to AlphaCentauri = 15 10 | Norrath to Arbre = 135 11 | Norrath to Snowdin = 75 12 | Norrath to Tambi = 82 13 | Norrath to Straylight = 54 14 | Tristram to AlphaCentauri = 118 15 | Tristram to Arbre = 122 16 | Tristram to Snowdin = 103 17 | Tristram to Tambi = 49 18 | Tristram to Straylight = 97 19 | AlphaCentauri to Arbre = 116 20 | AlphaCentauri to Snowdin = 12 21 | AlphaCentauri to Tambi = 18 22 | AlphaCentauri to Straylight = 91 23 | Arbre to Snowdin = 129 24 | Arbre to Tambi = 53 25 | Arbre to Straylight = 40 26 | Snowdin to Tambi = 15 27 | Snowdin to Straylight = 99 28 | Tambi to Straylight = 70 29 | -------------------------------------------------------------------------------- /2015/09/solve.js: -------------------------------------------------------------------------------- 1 | let {pairwise,flatMap,permutations,min,max} = require('../../utils/utils'); 2 | 3 | function solve(input, part) { 4 | let routeLengths = getRouteLengths(input); 5 | return part === 1 ? min(routeLengths) : max(routeLengths); 6 | } 7 | 8 | function expected(part) { 9 | return part == 1 ? 207 : 804; 10 | } 11 | 12 | function getPlaces(distances) { 13 | return Array.from(new Set(flatMap(distances,d => [d.from, d.to]))) 14 | } 15 | 16 | function getDistance (a,b,distances) { 17 | return distances.find(d => (d.from === a && d.to === b) || (d.to === a && d.from === b) ).distance; 18 | } 19 | 20 | function getDistances(input) { 21 | return input 22 | .map(s => /^(\w+) to (\w+) = (\d+)/g.exec(s)) 23 | .map(m => { return { from:m[1],to:m[2],distance:parseInt(m[3]) }}) 24 | } 25 | 26 | function getRouteLengths(input) { 27 | let distances = getDistances(input); 28 | let places = getPlaces(distances); 29 | return permutations(places) 30 | .map(r => pairwise(r).map(([a,b]) => getDistance(a,b,distances)).reduce((a,b) => a+b)); 31 | } 32 | 33 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/10/input.txt: -------------------------------------------------------------------------------- 1 | 1113122113 -------------------------------------------------------------------------------- /2015/10/solve.js: -------------------------------------------------------------------------------- 1 | let { range,flatMap,reduce } = require('../../utils/utils'); 2 | 3 | function solve(input, part) { 4 | return getRepeatedLength(part === 1 ? 40:50, input[0]); 5 | } 6 | 7 | function expected(part) { 8 | return part == 1 ? 360154 : 5103798; 9 | } 10 | 11 | let groupAdjacent = a => reduce(a,function(prev, curr) { 12 | if (prev.length && curr === prev[prev.length - 1][0]) { 13 | prev[prev.length - 1].push(curr); 14 | } 15 | else { 16 | prev.push([curr]); 17 | } 18 | return prev; 19 | }, []); 20 | 21 | const next = cur => [...flatMap(groupAdjacent(cur),g => [g.length, g[0]])] 22 | 23 | function getRepeatedLength(repetitions,input) { 24 | let start = Array.from(input).map(c => c - '0'); 25 | 26 | return [...range(1,repetitions)] 27 | .reduce(next, start).length; 28 | } 29 | 30 | module.exports = {solve,expected,groupAdjacent,next}; -------------------------------------------------------------------------------- /2015/11/input.txt: -------------------------------------------------------------------------------- 1 | vzbxkghb -------------------------------------------------------------------------------- /2015/11/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | var solver = part === 1 ? part1 : part2; 3 | return solver(input[0]); 4 | } 5 | 6 | function expected(part) { 7 | return part == 1 ? "vzbxxyzz" : "vzcaabcc"; 8 | } 9 | 10 | const valid = "abcdefghjkmnpqrstuvwxyz"; 11 | const lookup = {} 12 | for(let n = 1; n < valid.length; n++) { 13 | lookup[valid[n-1]] = valid[n]; 14 | } 15 | let run = ""; 16 | for(let n = 0; n < valid.length - 2; n++) { 17 | run += valid.slice(n,n+3) + "|"; 18 | } 19 | run = run.slice(0,-1); 20 | 21 | function getNext(curr) { 22 | let out = "" 23 | let carry = true; 24 | for(var n = curr.length-1; n >=0; n--) { 25 | if(carry && curr[n] === 'z') { 26 | out = 'a' + out; 27 | carry = true; 28 | } 29 | else if (carry) { 30 | // String.fromCharCode(curr.charCodeAt(n) + 1) 31 | out = lookup[curr[n]] + out; 32 | carry = false; 33 | } 34 | else { 35 | out = curr[n] + out; 36 | } 37 | } 38 | if (carry) out = "z" + out; 39 | return out; 40 | } 41 | 42 | function isValid(pwd) { 43 | return pwd.match(/(\w)\1.*(\w)\2/g) && pwd.match(run); 44 | } 45 | 46 | function getNextValid(curr) { 47 | do{ 48 | curr = getNext(curr); 49 | } while(!isValid(curr)) 50 | return curr; 51 | } 52 | 53 | function part1(input) { 54 | return getNextValid(input); 55 | } 56 | 57 | function part2(input) { 58 | return getNextValid(getNextValid(input)); 59 | } 60 | 61 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/12/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | var solver = part === 1 ? part1 : part2; 3 | return solver(input); 4 | } 5 | 6 | function expected(part) { 7 | return part == 1 ? 111754 : 65402; 8 | } 9 | 10 | function isRed(obj) { 11 | if (obj.constructor == Array) return false; 12 | for(let j in obj) { 13 | if (obj[j] === "red") return true; 14 | } 15 | return false; 16 | } 17 | 18 | function sum(obj,avoid) { 19 | let total = 0; 20 | if (typeof(obj) === "object") { 21 | if (!avoid(obj)) { 22 | for (let j in obj) { 23 | total += sum(obj[j],avoid); 24 | } 25 | } 26 | } 27 | else if (typeof (obj) === "number") { 28 | total += obj; 29 | } 30 | return total; 31 | } 32 | 33 | function part1(input) { 34 | let j = JSON.parse(input.join("\n")) 35 | return sum(j,(() => false)); 36 | } 37 | 38 | function part2(input) { 39 | let j = JSON.parse(input.join("\n")) 40 | return sum(j,isRed); 41 | } 42 | 43 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/13/input.txt: -------------------------------------------------------------------------------- 1 | Alice would lose 2 happiness units by sitting next to Bob. 2 | Alice would lose 62 happiness units by sitting next to Carol. 3 | Alice would gain 65 happiness units by sitting next to David. 4 | Alice would gain 21 happiness units by sitting next to Eric. 5 | Alice would lose 81 happiness units by sitting next to Frank. 6 | Alice would lose 4 happiness units by sitting next to George. 7 | Alice would lose 80 happiness units by sitting next to Mallory. 8 | Bob would gain 93 happiness units by sitting next to Alice. 9 | Bob would gain 19 happiness units by sitting next to Carol. 10 | Bob would gain 5 happiness units by sitting next to David. 11 | Bob would gain 49 happiness units by sitting next to Eric. 12 | Bob would gain 68 happiness units by sitting next to Frank. 13 | Bob would gain 23 happiness units by sitting next to George. 14 | Bob would gain 29 happiness units by sitting next to Mallory. 15 | Carol would lose 54 happiness units by sitting next to Alice. 16 | Carol would lose 70 happiness units by sitting next to Bob. 17 | Carol would lose 37 happiness units by sitting next to David. 18 | Carol would lose 46 happiness units by sitting next to Eric. 19 | Carol would gain 33 happiness units by sitting next to Frank. 20 | Carol would lose 35 happiness units by sitting next to George. 21 | Carol would gain 10 happiness units by sitting next to Mallory. 22 | David would gain 43 happiness units by sitting next to Alice. 23 | David would lose 96 happiness units by sitting next to Bob. 24 | David would lose 53 happiness units by sitting next to Carol. 25 | David would lose 30 happiness units by sitting next to Eric. 26 | David would lose 12 happiness units by sitting next to Frank. 27 | David would gain 75 happiness units by sitting next to George. 28 | David would lose 20 happiness units by sitting next to Mallory. 29 | Eric would gain 8 happiness units by sitting next to Alice. 30 | Eric would lose 89 happiness units by sitting next to Bob. 31 | Eric would lose 69 happiness units by sitting next to Carol. 32 | Eric would lose 34 happiness units by sitting next to David. 33 | Eric would gain 95 happiness units by sitting next to Frank. 34 | Eric would gain 34 happiness units by sitting next to George. 35 | Eric would lose 99 happiness units by sitting next to Mallory. 36 | Frank would lose 97 happiness units by sitting next to Alice. 37 | Frank would gain 6 happiness units by sitting next to Bob. 38 | Frank would lose 9 happiness units by sitting next to Carol. 39 | Frank would gain 56 happiness units by sitting next to David. 40 | Frank would lose 17 happiness units by sitting next to Eric. 41 | Frank would gain 18 happiness units by sitting next to George. 42 | Frank would lose 56 happiness units by sitting next to Mallory. 43 | George would gain 45 happiness units by sitting next to Alice. 44 | George would gain 76 happiness units by sitting next to Bob. 45 | George would gain 63 happiness units by sitting next to Carol. 46 | George would gain 54 happiness units by sitting next to David. 47 | George would gain 54 happiness units by sitting next to Eric. 48 | George would gain 30 happiness units by sitting next to Frank. 49 | George would gain 7 happiness units by sitting next to Mallory. 50 | Mallory would gain 31 happiness units by sitting next to Alice. 51 | Mallory would lose 32 happiness units by sitting next to Bob. 52 | Mallory would gain 95 happiness units by sitting next to Carol. 53 | Mallory would gain 91 happiness units by sitting next to David. 54 | Mallory would lose 66 happiness units by sitting next to Eric. 55 | Mallory would lose 75 happiness units by sitting next to Frank. 56 | Mallory would lose 99 happiness units by sitting next to George. 57 | -------------------------------------------------------------------------------- /2015/13/solve.js: -------------------------------------------------------------------------------- 1 | let {permutations,pairwise,max} = require("../../utils/utils"); 2 | 3 | function solve(input, part) { 4 | let rules = input 5 | .map(s => s.match(/(\w+) would (lose|gain) (\d+) happiness units by sitting next to (\w+)\./)) 6 | .map(p => { return { A: p[1], B: p[4], Gain: parseInt(p[3]) * (p[2] === "lose" ? -1 : 1) }}); 7 | let people = Array.from(new Set(rules.map(r => r.A))); 8 | let lookup = rules.reduce((a,r) => { a[`${r.A}-${r.B}`] = r.Gain; return a}, {}); 9 | if (part == 2) { 10 | people.forEach(p => { lookup[`Mark-${p}`] = 0; lookup[`${p}-Mark`] = 0; }); 11 | people.push("Mark"); 12 | } 13 | 14 | let lookupHappiness = ([a,b]) => lookup[`${a}-${b}`] + lookup[`${b}-${a}`]; 15 | var happiness = permutations(Array.from(people) 16 | .slice(1)) 17 | .map(p => { p.unshift(people[0]); p.push(people[0]); return pairwise(p); }) 18 | .map(p => p.reduce((acc,x) => { return acc + lookupHappiness(x); },0)); 19 | return max(happiness) 20 | } 21 | 22 | function expected(part) { 23 | return part == 1 ? 664 : 640; 24 | } 25 | 26 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/14/input.txt: -------------------------------------------------------------------------------- 1 | Dancer can fly 27 km/s for 5 seconds, but then must rest for 132 seconds. 2 | Cupid can fly 22 km/s for 2 seconds, but then must rest for 41 seconds. 3 | Rudolph can fly 11 km/s for 5 seconds, but then must rest for 48 seconds. 4 | Donner can fly 28 km/s for 5 seconds, but then must rest for 134 seconds. 5 | Dasher can fly 4 km/s for 16 seconds, but then must rest for 55 seconds. 6 | Blitzen can fly 14 km/s for 3 seconds, but then must rest for 38 seconds. 7 | Prancer can fly 3 km/s for 21 seconds, but then must rest for 40 seconds. 8 | Comet can fly 18 km/s for 6 seconds, but then must rest for 103 seconds. 9 | Vixen can fly 18 km/s for 5 seconds, but then must rest for 84 seconds. 10 | -------------------------------------------------------------------------------- /2015/14/solve.js: -------------------------------------------------------------------------------- 1 | let {scan,range,max} = require("../../utils/utils"); 2 | 3 | function solve(input, part) { 4 | let lookup = getLookup(input); 5 | if (part === 1) { 6 | return max(lookup, v => v[v.length-1]); 7 | } 8 | else { 9 | return max(lookup, v => v.filter((n,t) => n===max(lookup,q => q[t])).length); 10 | } 11 | } 12 | 13 | function expected(part) { 14 | return part === 1 ? 2640 : 1102; 15 | } 16 | 17 | function getLookup(input) { 18 | return input.map(s => s.split(' ')) 19 | .map(g => { return { Speed:Number(g[3]), Duration:Number(g[6]), Rest:Number(g[13]) } }) 20 | .map(r => Array.from(scan(Array.from(range(0, 2503)) 21 | .map(t => t % (r.Duration + r.Rest) < r.Duration ? r.Speed : 0) 22 | , (a, b) => a + b, 0)).slice(1)); 23 | } 24 | 25 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/15/input.txt: -------------------------------------------------------------------------------- 1 | Frosting: capacity 4, durability -2, flavor 0, texture 0, calories 5 2 | Candy: capacity 0, durability 5, flavor -1, texture 0, calories 8 3 | Butterscotch: capacity -1, durability 0, flavor 5, texture 0, calories 6 4 | Sugar: capacity 0, durability 0, flavor -2, texture 2, calories 1 5 | -------------------------------------------------------------------------------- /2015/15/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | let ingredients = input.map(f => f.match(/-?\d+/g).map(n => Number(n))); 3 | let max = -1; 4 | for(let c of distribute4(100)) { 5 | let s = scoreCookie(ingredients, c); 6 | if (part == 2 && s.calories != 500) s.score= -1; 7 | max = Math.max(s.score,max); 8 | } 9 | return max; 10 | } 11 | 12 | function expected(part) { 13 | return part == 1 ? 18965440 : 15862900; 14 | } 15 | 16 | function* distribute4(max) { 17 | for (let a = 0; a <= max; a++) 18 | for (let b = 0; b <= max - a; b++) 19 | for (let c = 0; c <= max - a - b; c++) 20 | yield [ a, b, c, max - a - b - c ]; 21 | } 22 | 23 | function scoreCookie(ingredients, amounts) { 24 | let total = [0,0,0,0,0] 25 | for(let n = 0; n < ingredients.length; n++) { 26 | ingredients[n].forEach((t,q) => total[q] += t * amounts[n]); 27 | } 28 | let score = (Math.max(0,total[0]) * Math.max(0,total[1]) * Math.max(0,total[2]) * Math.max(0,total[3])) 29 | return { score, calories:total[4]}; 30 | } 31 | 32 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/16/solve.js: -------------------------------------------------------------------------------- 1 | let { matches } = require('../../utils/utils') 2 | 3 | function solve(input, part) { 4 | let sues = input.map(s => [...matches(s,/(\w+): (\d+)/g)].reduce((acc,m) => { 5 | acc[m[1]] = Number(m[2]); return acc;} ,{} )); 6 | 7 | if (part === 1) { 8 | return sues.findIndex(s => every(s,f1)) + 1; 9 | } 10 | return sues.findIndex(s => every(s,f2)) + 1; 11 | } 12 | 13 | // equivalent of Array.every for an object 14 | function every(obj, matcher) { 15 | for(var prop in obj) { 16 | if (!matcher(prop, obj[prop])) return false; 17 | } 18 | return true; 19 | } 20 | 21 | 22 | 23 | let clues = { 24 | children: 3, 25 | cats: 7, 26 | samoyeds: 2, 27 | pomeranians: 3, 28 | akitas: 0, 29 | vizslas: 0, 30 | goldfish: 5, 31 | trees: 3, 32 | cars: 2, 33 | perfumes: 1 34 | }; 35 | 36 | let f1 = (t,n) => clues[t] === n; 37 | function f2(t,n) { 38 | if (t === "cats" || t === "trees") return n > clues[t]; 39 | if (t === "pomeranians" || t === "goldfish") return n < clues[t]; 40 | return n === clues[t]; 41 | } 42 | 43 | function expected(part) { 44 | return part == 1 ? 213 : 323; 45 | } 46 | 47 | 48 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/17/input.txt: -------------------------------------------------------------------------------- 1 | 11 2 | 30 3 | 47 4 | 31 5 | 32 6 | 36 7 | 3 8 | 1 9 | 5 10 | 3 11 | 32 12 | 36 13 | 15 14 | 11 15 | 46 16 | 26 17 | 28 18 | 1 19 | 19 20 | 3 21 | -------------------------------------------------------------------------------- /2015/17/solve.js: -------------------------------------------------------------------------------- 1 | let {min} = require('../../utils/utils') 2 | 3 | function solve(input, part) { 4 | let containers = input.map(s => Number(s)); 5 | let perms = Array.from(distribute([], containers, 150, 0)); 6 | if (part === 1) { 7 | return perms.length; 8 | } 9 | let m = min(perms,f => f.length); 10 | return perms.filter(a => a.length === m).length; 11 | } 12 | 13 | function* distribute(used, pool, target, runningTotal) 14 | { 15 | if (pool.length > 0) { 16 | let h = pool[0]; 17 | let tail = pool.slice(1); 18 | if (h + runningTotal === target) 19 | yield Array(...used,h); 20 | else if (h + runningTotal < target) 21 | yield* distribute(Array(...used,h), tail, target, h + runningTotal); 22 | yield* distribute(used, tail, target, runningTotal); 23 | } 24 | } 25 | 26 | function expected(part) { 27 | return part == 1 ? 4372 : 4; 28 | } 29 | 30 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/18/input.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 | #####.##...#..#.#.#.......#.##..#####..#####...###..##.#.#..###.#.#####.####..#.#..##...#.##...#.### 41 | .##.#..#######.###.#.####.....##...#.##.#.#..#...##....####......######.#..######.....##########.##. 42 | ##...#.#..#.##.###.#.#.#.##.###.##..##.##.##...#.#..###.#######..#.....#####..#....######.#..##..### 43 | .#.#.###.....#..##..#.#..##..#.###...###.#..##...#...#.#####.#.#####..###.#..#...##..#.#..#..####... 44 | .#......##..#.....####.###....##.###.....###.##........#.###.##..#..#.#######.#.######..##..###..... 45 | ..##.#.#..#.##...#.###.###...######..#..#.#..#....###.#.#....#..........#...##.##.##.#..##..#.#####. 46 | ###.###.#..#.##..##.#..#..##.....##.....#..#######.#..#.#.#.####.###..###.#.#..#.##.##.####.###.#### 47 | #.#.#..#....########.#..#..#...##..#.##..#.#..##..####...##.....#.##.#.#...########..#.###.#..#.#.## 48 | .##.....#...#.#...##.##....###...##..#.####...#..#.#..#..#.##..#.###.##.####.##..####.....##.#.....# 49 | ....####.#.##.#.##.#..##.#.######.##.####..#...####.#..###.#.#..#..##.#.#.....##.#####.#.####...#.#. 50 | #..#####.#####.....##....######..##....#..#.#.###.#####.....##.##.####.#...##...#.##.#.#####.##.#... 51 | ##.####..###.#....#...#.#.#.#.###.#####.#.####..####...####......##..#..#..#.#.##...########....#... 52 | .###.#.#.#.#..####.##.#..######..#.#.###.....#.#......#.#.#.#..####.##...##.#####.#.##..##..#..#.#.. 53 | .....###...#...#.####.###.#.#.#.#.....#....#.####.###.##.##.##.#######......#.####......#....##..... 54 | ##..#..#.#.##..#...#..##.##.##..###.#....##.##....####.#.##.###....#.##.#.#.##...##.###...#..#..#### 55 | ...#.#..##..##.#...##.##...#.#......#.#.##..###....####.##...#.#.###.#..#..#.####..##..##..#####.### 56 | .##.##..##########.##...#.##.####.#.#######.##.#.##.##..#...##....########.###..##.##.##.#..##.#.#.# 57 | #####.#....#.##..#.....#......##.##..#.##.###..##.......###..##.#.###.##.###....####.#..#.###..#.#.# 58 | .#...#..#.##....##....#...####....#...#..#...####...########.###.#..##.#.#.##..###..#.#.###.....##.# 59 | ##..##.....###......#..###.##.####.##.####.#.#....#..#...#..#.#..#.###.#...#...#..##.##...#..####### 60 | .....##..###..##...#####.#.#.....###.#.#..####...#.#.#..#..####..##.#..###.####.#....##..###....#..# 61 | #.#.##.#....#.#####.#....##...#...##...##....#.#.......#....#..#...###.###.#.####..####....#.##.#.#. 62 | ..##...##..###.#.#.##.#..#....#.#.....##.###.#.###.###.....#...#.#..#######.#####..#.###...##......# 63 | #......###..#....#.#..#.###.##.#...##..###.####.#.#....#.##..#.###..##.#..#####..##.###.....#..###.. 64 | ##.#.##..##.###.#..##.....#.##.....###....##.####.######.#...#..###....#.#...#.##.....###....#..#.#. 65 | .##.#.#.#.##..#.#.#..##..#.###.####....#..###.######..####.#.....###.##..#...###.#..######.##.#.##.. 66 | ...##.####.#..##.#####.##.#...##..#..#...#.#.#.#####...#....#..###...#..#....#.#.##.#.######.#..#### 67 | ..#.#.#.#...#.######.#.....#..#.#..###....#.#.########...#....#.#.##..#...##...#.#..#.#.###....##... 68 | #####..#..##..#..##..#..#.#.##.#....#####.####.##.#.###..##..##....#.....#.#####.#...#.#####.##.#.#. 69 | #.#..#####...####.###.###.....####.###.....##...##...#..#..#######.#.##....##..####.....##...#..#..# 70 | #.#.###.#.#..##..#....#.#...#.#.##.##..#.##.....##...#.#..##.......##.#.###..#####.#.##....#.##..... 71 | ...#.......#....#.#.####.#.###.###..#....#..##.#..####........#.##..#...#.#...###.#..#.#.#...#...#.. 72 | ...##.#####.##.#.###.##.##.#.##..##.#.#.#.#.#.##.#..##...##.#.#..#..##.##.#####.#.###...#####..#..#. 73 | #######.#..#..#....##.#.#..####.#..#..###...#..#.......###.#.#.####....#.###...#.#.###.#.#.#.#..###. 74 | ..##.##.#.##.###....###.##.#.###.#...#....#.####..###..###.#.#..#...##.#.#.#..##.###..###.#.##...### 75 | ######..######..##..##.#.#.##.##.#..##..#.#.#.##..#.#...#...#.#.#..######.#..#.#.######..#......##.# 76 | #.#####.....#.......#########..###.##...#...##.#.#..#...#####...#...#..#.###.#..#.#...###.#.#.#...#. 77 | #....##....###...##.##.#...##.........##.#.#..#.#.##.#.######.#####..#..###.###.#...#.#.##.######... 78 | #.#...###.#.###.##.#.######.#######.###.##..#.#.#...######.##.####.##..#.#.#.#......##..##.........# 79 | ..###..##....#.....##...#.#.###.#.#.....##.#...###.####.#...#...##..##.#.#.####..###...######....#.# 80 | ..###.#.##.####.#..#.##....##..#####....#..##.##.#..#######...#.####...##.#.#.##.........#....#....# 81 | .##.#...#.####..#.#...#.##..######.##..##.#.###.##..###.###....##..#.##.##..##.#...###.##.##.###.... 82 | #...###.###.#..#....#.......#..#.....###..#.###.##.##....#.####.#.####.##..##..#..#.....#....##.#.#. 83 | .##.#..#..#.##.......#.####.#######.....#.##.##.#.....#.#..#....######.#..###.##.##.....#.####..##.# 84 | ###..#.###.#..####.....##....#..####....#.##.##..#...######.#########...#.#....##...###.#..#.##...#. 85 | #..###..##..#.#.##.###.#.#.##...###.#...##.##..#.###....###..#.#...#.###..######.#..#.###..#..#..#.# 86 | .#........##.#.###..###.#.#.##.....##.##.#.#...##..#.##....###..#.#.#.#.##....#.##..#.#...###...#... 87 | ####.####..#....#.#.#..#..##.......##.####...###.##..#.#.##.#..##..######.......##.#.##..#...#.....# 88 | ..#..#..###..##.##..######.#..###..###.#.##..##.#..#####.#.#.#.##..#.##..##.##......####.#.......... 89 | ...##.##..###.#...###....#.#.#.#.....#.##.....##...#...#......####...##.##....##.#..#.####.#..###.#. 90 | ..#.....####.#.###.#####..#..###..#..#.#...#####...###.###....#.###..#...#..#..#.#..#.##..##.#.#.... 91 | ..##.#####...###.###.........#....##.####.##..#.#..#.#...#...##.##.##..#.#.##.########......#####... 92 | ...###.#.#..#...#.###.###.......##.###.#..#.##########...#..#.#.#.##.#.###...######..#.#...###.##... 93 | .#.#.#######.#..##.##..##...#...####...#..#####.#..##...###.#.#...#.##...#......#..##.####..#.....## 94 | .##.##.#.#......#######..###.....##.#.##..###......#....####...#.###.#.##.#........#..#....##.....## 95 | #...#.###.#.##...##.####....#...#.###..#.#.....#.#....#.#.#.##...#.#..#####.#.#..#..#..#....#...#### 96 | .....##...###......#####..##.##.##...##.#.#####..##...#.#.#.#.###...###.##.####..#.#..#.#..#.####.## 97 | #..#..##.#.##.#.##.#.#.#..###....###.##.#.##.#...#.#..#...#....###.#..#.#.######.#...####..#..##.#.# 98 | #..#.#..#...###.#..##.#...#...##.#......#...#..#..####..##.....#.###...#.#..#.#....#.#####.##.###... 99 | ###....#.#..#.#..###..#.##......#...#..#..##.#..###..##..#..#.####..#...########..##.#.##.#.#.#...#. 100 | .#.#.##.##.###..#...#.#....#..#.##..#.#.#.#.##.##.#####...#........####..###..####.#####..#.##.#.##. 101 | -------------------------------------------------------------------------------- /2015/18/solve.js: -------------------------------------------------------------------------------- 1 | let {range,sumBy} = require("../../utils/utils"); 2 | 3 | function solve(input, part) { 4 | let state = input.map(s => Array.from(s.trim()).map(c => c === '#' ? 1 : 0)); 5 | const repetitions = 100; 6 | let getNextValue = (part === 1) ? getNextValue1 : getNextValue2; 7 | let getLight = (part === 1) ? getLight1 : getLight2; 8 | for (let a = 0; a < repetitions; a++) { 9 | let nextState = [...range(0, state.length)] 10 | .map(x => [...range(0, state[x].length)] 11 | .map(y => getNextValue(getLight, state, x, y))); 12 | state = nextState; 13 | } 14 | return sumBy(state, r => sumBy(r)); 15 | } 16 | 17 | let getLight1 = (state, x, y) => { 18 | if (x < 0 || x >= state.length) return 0; 19 | if (y < 0 || y >= state[x].length) return 0; 20 | return state[x][y]; 21 | }; 22 | 23 | let getLight2 = (state, x, y) => { 24 | if (x < 0 || x >= state.length) return 0; 25 | if (y < 0 || y >= state[x].length) return 0; 26 | if (x == 0 && y == 0) return 1; 27 | if (x == state.length - 1 && y == 0) return 1; 28 | if (x == 0 && y == state[x].length - 1) return 1; 29 | if (x == state.length - 1 && y == state[x].length - 1) return 1; 30 | return state[x][y]; 31 | }; 32 | 33 | let getNeighbourSum = (getLight, state, x, y) => getLight(state, x - 1, y - 1) + 34 | getLight(state, x, y - 1) + 35 | getLight(state, x + 1, y - 1) + 36 | getLight(state, x - 1, y) + 37 | getLight(state, x + 1, y) + 38 | getLight(state, x - 1, y + 1) + 39 | getLight(state, x, y + 1) + 40 | getLight(state, x + 1, y + 1); 41 | 42 | 43 | let getNextValue1 = (getLight, state, x, y) => { 44 | return getNeighbourSum(getLight, state, x, y) === 3 ? 1 : 45 | (getNeighbourSum(getLight, state, x, y) === 2 && getLight(state, x, y) === 1) ? 1 : 0; 46 | }; 47 | 48 | let getNextValue2 = (getLight, state, x, y) => { 49 | if (x == 0 && y == 0) return 1; 50 | if (x == state.length - 1 && y == 0) return 1; 51 | if (x == 0 && y == state[x].length - 1) return 1; 52 | if (x == state.length - 1 && y == state[x].length - 1) return 1; 53 | 54 | return getNeighbourSum(getLight, state, x, y) === 3 ? 1 : 55 | (getNeighbourSum(getLight, state, x, y) === 2 && getLight(state, x, y) === 1) ? 1 : 0; 56 | }; 57 | 58 | function expected(part) { 59 | return part == 1 ? 814 : 924; 60 | } 61 | 62 | 63 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/19/input.txt: -------------------------------------------------------------------------------- 1 | Al => ThF 2 | Al => ThRnFAr 3 | B => BCa 4 | B => TiB 5 | B => TiRnFAr 6 | Ca => CaCa 7 | Ca => PB 8 | Ca => PRnFAr 9 | Ca => SiRnFYFAr 10 | Ca => SiRnMgAr 11 | Ca => SiTh 12 | F => CaF 13 | F => PMg 14 | F => SiAl 15 | H => CRnAlAr 16 | H => CRnFYFYFAr 17 | H => CRnFYMgAr 18 | H => CRnMgYFAr 19 | H => HCa 20 | H => NRnFYFAr 21 | H => NRnMgAr 22 | H => NTh 23 | H => OB 24 | H => ORnFAr 25 | Mg => BF 26 | Mg => TiMg 27 | N => CRnFAr 28 | N => HSi 29 | O => CRnFYFAr 30 | O => CRnMgAr 31 | O => HP 32 | O => NRnFAr 33 | O => OTi 34 | P => CaP 35 | P => PTi 36 | P => SiRnFAr 37 | Si => CaSi 38 | Th => ThCa 39 | Ti => BP 40 | Ti => TiTi 41 | e => HF 42 | e => NAl 43 | e => OMg 44 | 45 | CRnCaSiRnBSiRnFArTiBPTiTiBFArPBCaSiThSiRnTiBPBPMgArCaSiRnTiMgArCaSiThCaSiRnFArRnSiRnFArTiTiBFArCaCaSiRnSiThCaCaSiRnMgArFYSiRnFYCaFArSiThCaSiThPBPTiMgArCaPRnSiAlArPBCaCaSiRnFYSiThCaRnFArArCaCaSiRnPBSiRnFArMgYCaCaCaCaSiThCaCaSiAlArCaCaSiRnPBSiAlArBCaCaCaCaSiThCaPBSiThPBPBCaSiRnFYFArSiThCaSiRnFArBCaCaSiRnFYFArSiThCaPBSiThCaSiRnPMgArRnFArPTiBCaPRnFArCaCaCaCaSiRnCaCaSiRnFYFArFArBCaSiThFArThSiThSiRnTiRnPMgArFArCaSiThCaPBCaSiRnBFArCaCaPRnCaCaPMgArSiRnFYFArCaSiThRnPBPMgAr 46 | -------------------------------------------------------------------------------- /2015/19/solve.js: -------------------------------------------------------------------------------- 1 | let {range,shuffle} = require("../../utils/utils"); 2 | 3 | 4 | function solve(input, part) { 5 | let replacements = input 6 | .map(s => s.split(' ')) 7 | .filter(a => a.length === 3) 8 | .map(a => [ a[0], a[2] ]); 9 | 10 | let medicineMolecule = input[input.length - 1]; 11 | if (part === 1) { 12 | return new Set(mutate(medicineMolecule,replacements)).size; 13 | } 14 | else { 15 | return search(medicineMolecule, replacements); 16 | } 17 | } 18 | 19 | function* mutate(sq, replacements) { 20 | for(let pos of range(0, sq.length)) { 21 | for(let rep of replacements) { 22 | let [a,b] = rep; 23 | if(sq.substring(pos).startsWith(a)) { 24 | yield sq.substring(0,pos) + b + sq.substring(pos+a.length); 25 | } 26 | } 27 | } 28 | } 29 | 30 | function search (molecule, replacements) { 31 | let target = molecule; 32 | let mutations = 0; 33 | 34 | while (target != "e") { 35 | let tmp = target; 36 | for (let rep of replacements) { 37 | let [a,b] = rep; 38 | var index = target.indexOf(b); 39 | if (index >= 0) 40 | { 41 | target = target.substring(0, index) + a + target.substring(index + b.length); 42 | mutations++; 43 | } 44 | } 45 | 46 | if (tmp === target) { 47 | target = molecule; 48 | mutations = 0; 49 | shuffle(replacements); 50 | } 51 | } 52 | return mutations; 53 | } 54 | 55 | function expected(part) { 56 | return part === 1 ? 509 : 195; 57 | } 58 | 59 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/20/input.txt: -------------------------------------------------------------------------------- 1 | 36000000 -------------------------------------------------------------------------------- /2015/20/solve.js: -------------------------------------------------------------------------------- 1 | 2 | function solve(input, part) { 3 | const target = Number(input[0]); 4 | 5 | let presentsPerHouse = part === 1 ? 10 : 11; 6 | let houses = new Array(Math.trunc(target/presentsPerHouse) + 1).fill(0); 7 | 8 | for (let elf = 1; elf < houses.length; elf++) 9 | for (let house = elf, n = 0; house < houses.length && (part === 1 || n < 50); house+=elf, n++) 10 | houses[house] += elf * presentsPerHouse; 11 | for (let house = 1; house < houses.length; house++) 12 | if (houses[house] > target) { return house; } 13 | } 14 | 15 | const expected = part => part === 1 ? 831600 : 884520; 16 | 17 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/21/input.txt: -------------------------------------------------------------------------------- 1 | Hit Points: 103 2 | Damage: 9 3 | Armor: 2 4 | -------------------------------------------------------------------------------- /2015/21/solve.js: -------------------------------------------------------------------------------- 1 | let {maxBy,minBy} = require("../../utils/utils"); 2 | 3 | function solve(input, part) { 4 | 5 | let boss = new PlayerStatus(103, 9, 2, 0); 6 | let options = Array.from(getPlayerOptions(100)); 7 | if(part === 1) { 8 | return minBy(options.filter(x => battle(x, boss)), x => x.goldSpent).goldSpent; 9 | } 10 | else { 11 | return maxBy(options.filter(x => !battle(x, boss)), x => x.goldSpent).goldSpent; 12 | } 13 | } 14 | 15 | 16 | class ShopItem { 17 | constructor(name, cost, damage, armor) { 18 | this.name = name; 19 | this.cost = cost; 20 | this.damage = damage; 21 | this.armor = armor; 22 | } 23 | } 24 | 25 | let weapons = [ 26 | new ShopItem("Dagger",8,4,0), 27 | new ShopItem("Shortsword",10,5,0), 28 | new ShopItem("Warhammer",25,6,0), 29 | new ShopItem("Longsword",40,7,0), 30 | new ShopItem("Greataxe",74,8,0), 31 | ] 32 | 33 | let armory = [ 34 | new ShopItem("Leather",13,0,1), 35 | new ShopItem("Chainmail",31,0,2), 36 | new ShopItem("Splintmail",53,0,3), 37 | new ShopItem("Bandedmail",75,0,4), 38 | new ShopItem("Platemail",102,0,5), 39 | ] 40 | 41 | function* getPlayerOptions(hitPoints) { 42 | let startStatus = new PlayerStatus(hitPoints,0,0,0); 43 | for (let weapon of weapons) 44 | { 45 | var ps = startStatus.powerupWith(weapon); 46 | yield ps; 47 | yield* addRings(ps); 48 | for (let armor of armory) 49 | { 50 | let ps2 = ps.powerupWith(armor); 51 | yield ps2; 52 | yield* addRings(ps2); 53 | } 54 | } 55 | } 56 | 57 | let rings = [ 58 | new ShopItem("Damage +1", 25,1,0), 59 | new ShopItem("Damage +2", 50,2,0), 60 | new ShopItem("Damage +3", 100,3,0), 61 | new ShopItem("Defense +1", 20,0,1), 62 | new ShopItem("Defense +2", 40,0,2), 63 | new ShopItem("Defense +3", 80,0,3) 64 | ] 65 | 66 | function* addRings(status) 67 | { 68 | for (let ring1 of rings) 69 | { 70 | let with1Ring = status.powerupWith(ring1); 71 | yield with1Ring; 72 | for (let ring2 of rings) 73 | { 74 | if (ring2 != ring1) { 75 | yield with1Ring.powerupWith(ring2); 76 | } 77 | } 78 | } 79 | } 80 | 81 | 82 | function battle(player, boss, debug = false) 83 | { 84 | while (player.hitPoints > 0 && boss.hitPoints > 0) 85 | { 86 | boss = boss.hitBy(player); 87 | if (debug) console.log(`Boss: ${boss.hitPoints}`); 88 | if (boss.hitPoints <= 0) break; 89 | player = player.hitBy(boss); 90 | if (debug) console.log(`Player: ${player.hitPoints}`); 91 | } 92 | return player.hitPoints > 0; 93 | } 94 | 95 | class PlayerStatus 96 | { 97 | constructor(hp, d, a, g, s = "") 98 | { 99 | this.hitPoints = hp; 100 | this.damage = d; 101 | this.armor = a; 102 | this.goldSpent = g; 103 | this.setup = s; 104 | } 105 | 106 | powerupWith(item) { 107 | return new PlayerStatus(this.hitPoints, this.damage + item.damage, this.armor + item.armor, this.goldSpent + item.cost, this.setup + "," + item.name); 108 | } 109 | 110 | hitBy(opponent) { 111 | return new PlayerStatus(this.hitPoints - opponent.damage + this.armor, this.damage, this.armor, this.goldSpent, this.setup); 112 | } 113 | } 114 | 115 | 116 | function expected(part) { 117 | return part == 1 ? 121 : 201; 118 | } 119 | 120 | 121 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/22/input.txt: -------------------------------------------------------------------------------- 1 | Hit Points: 58 2 | Damage: 9 -------------------------------------------------------------------------------- /2015/22/solve.js: -------------------------------------------------------------------------------- 1 | // my solution with random spell chooser: http://markheath.net/post/advent-of-code-day22 2 | // this simpler JavaScript version inspired by https://www.reddit.com/r/adventofcode/comments/3xspyl/day_22_solutions/cy7swgm/ 3 | 4 | function solve(input, part) { 5 | let bossH = 58; // hit points 6 | let bossAt = 9; // boss attack 7 | 8 | let costMissile = 53; 9 | let costDrain = 73; 10 | let costPoison = 173; 11 | let costShield = 113; 12 | let costRecharge = 229; 13 | 14 | const heroH = 50; 15 | const heroMana = 500; 16 | 17 | let heroAr = 0; 18 | let cost = 0; 19 | 20 | let poison = 0; 21 | let recharge = 0; 22 | let shield = 0; 23 | 24 | let boss; 25 | let hero; 26 | let mana; 27 | 28 | let answer = 9999999; 29 | for(let i = 0; i < 3000000; i++) { 30 | if(fight()) { 31 | answer = Math.min(answer, cost); 32 | //console.log(answer); 33 | } 34 | } 35 | return answer; 36 | 37 | function choose() { 38 | if(mana < costPoison) { 39 | return "nothing"; 40 | } 41 | 42 | for(;;) { 43 | let next = Math.floor(Math.random() * 5); 44 | if (next == 0 && mana >= costMissile) { 45 | return "missile"; 46 | } 47 | else if (next === 1 && mana >= costDrain) { 48 | return "drain"; 49 | } 50 | else if (next === 2 && mana >= costPoison) { 51 | return "poison"; 52 | } 53 | else if (next === 3 && mana >= costRecharge) { 54 | return "recharge"; 55 | } 56 | else if (next === 4 && mana >= costShield) { 57 | return "shield"; 58 | } 59 | } 60 | } 61 | 62 | function fight() { 63 | let turn = true; 64 | let type = "nothing"; 65 | 66 | hero = heroH; 67 | boss = bossH; 68 | mana = heroMana; 69 | cost = 0; 70 | poison = 0; 71 | recharge = 0; 72 | shield = 0; 73 | 74 | for (;;) { 75 | if(poison > 0) { 76 | poison--; 77 | boss -= 3; 78 | } 79 | 80 | if(recharge > 0) { 81 | recharge--; 82 | mana += 101; 83 | } 84 | 85 | if(shield > 0) { 86 | shield--; 87 | } 88 | 89 | if(shield == 0) { 90 | heroAr = 0; 91 | } 92 | 93 | if (boss <= 0) { 94 | return true; 95 | } 96 | 97 | if (hero <= 0) { 98 | return false; 99 | } 100 | 101 | if (turn) { 102 | if (part === 2) { 103 | // hard mode 104 | hero--; 105 | } 106 | if(hero <= 0) { 107 | return false; 108 | } 109 | 110 | type = choose(); 111 | if (type == "nothing") { 112 | return false; 113 | } 114 | 115 | if(type == "drain") { 116 | boss -= 2; 117 | hero += 2; 118 | cost += costDrain; 119 | mana -= costDrain; 120 | } 121 | else if (type == "missile") { 122 | boss -= 4; 123 | cost += costMissile; 124 | mana -= costMissile; 125 | } 126 | else if (type == "poison") { 127 | poison = 6; 128 | cost += costPoison; 129 | mana -= costPoison; 130 | } 131 | else if (type == "recharge") { 132 | recharge = 5; 133 | cost += costRecharge; 134 | mana -= costRecharge; 135 | } 136 | else if (type == "shield") { 137 | shield = 6; 138 | heroAr = 7; 139 | cost += costShield; 140 | mana -= costShield; 141 | } 142 | } 143 | else { 144 | hero -= Math.max(1, bossAt - heroAr); 145 | } 146 | turn = !turn; 147 | } 148 | } 149 | } 150 | 151 | function expected(part) { 152 | return part === 1 ? 1269 : 1309; 153 | } 154 | 155 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/23/input.txt: -------------------------------------------------------------------------------- 1 | jio a, +19 2 | inc a 3 | tpl a 4 | inc a 5 | tpl a 6 | inc a 7 | tpl a 8 | tpl a 9 | inc a 10 | inc a 11 | tpl a 12 | tpl a 13 | inc a 14 | inc a 15 | tpl a 16 | inc a 17 | inc a 18 | tpl a 19 | jmp +23 20 | tpl a 21 | tpl a 22 | inc a 23 | inc a 24 | tpl a 25 | inc a 26 | inc a 27 | tpl a 28 | inc a 29 | tpl a 30 | inc a 31 | tpl a 32 | inc a 33 | tpl a 34 | inc a 35 | inc a 36 | tpl a 37 | inc a 38 | inc a 39 | tpl a 40 | tpl a 41 | inc a 42 | jio a, +8 43 | inc b 44 | jie a, +4 45 | tpl a 46 | inc a 47 | jmp +2 48 | hlf a 49 | jmp -7 50 | -------------------------------------------------------------------------------- /2015/23/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | 3 | var instructions = input.map(i => i.split(' ').map(s => s.replace(',',''))); 4 | if (part === 1) { 5 | return runInstructions({ a: 0, b: 0 },instructions).b; 6 | } 7 | else { 8 | return runInstructions({ a: 1, b: 0 },instructions).b; 9 | } 10 | } 11 | 12 | function runInstructions(registers, instructions) { 13 | let index = 0; 14 | while (index < instructions.length) { 15 | var ins = instructions[index]; 16 | switch (ins[0]) { 17 | case "inc": 18 | registers[ins[1]]++; 19 | index++; 20 | break; 21 | case "tpl": 22 | registers[ins[1]] *= 3; 23 | index++; 24 | break; 25 | case "hlf": 26 | registers[ins[1]] /= 2; 27 | index++; 28 | break; 29 | case "jio": 30 | index += registers[ins[1]] == 1 ? parseInt(ins[2]) : 1; 31 | break; 32 | case "jie": 33 | index += registers[ins[1]] % 2 == 0 ? parseInt(ins[2]) : 1; 34 | break; 35 | case "jmp": 36 | index += parseInt(ins[1]); 37 | break; 38 | default: 39 | throw new Error("not implemented " + ins[0]); 40 | } 41 | } 42 | return registers; 43 | } 44 | 45 | function expected(part) { 46 | return part == 1 ? 184 : 231; 47 | } 48 | 49 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/24/input.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 5 5 | 7 6 | 13 7 | 17 8 | 19 9 | 23 10 | 29 11 | 31 12 | 37 13 | 41 14 | 43 15 | 53 16 | 59 17 | 61 18 | 67 19 | 71 20 | 73 21 | 79 22 | 83 23 | 89 24 | 97 25 | 101 26 | 103 27 | 107 28 | 109 29 | 113 -------------------------------------------------------------------------------- /2015/24/solve.js: -------------------------------------------------------------------------------- 1 | let {sumBy} = require("../../utils/utils"); 2 | 3 | let bestSoFar; 4 | function solve(input, part) { 5 | var presents = input.map(n => Number(n)); 6 | return findBestQE(presents, part === 1 ? 3:4); 7 | } 8 | 9 | function findBestQE(presents, groups) 10 | { 11 | let totalWeight = sumBy(presents); 12 | let weightPerSet = totalWeight / groups; 13 | bestSoFar = 1 + presents.length / groups; 14 | let bestSet = [...distribute([], presents, Math.floor(weightPerSet))] 15 | .map(g => { return { count: g.length, qe: g.reduce((a, b) => a * b, 1) } }) 16 | .sort((a,b) => (a.count === b.count) ? a.qe - b.qe : a.count - b.count )[0] 17 | return bestSet.qe; 18 | } 19 | 20 | function* distribute(used, pool, amount) 21 | { 22 | if (used.length >= bestSoFar) return; 23 | 24 | let remaining = amount - sumBy(used); 25 | for (let n = 0; n < pool.length; n++) { 26 | let s = pool[n]; 27 | if (pool[n] > remaining) continue; 28 | let x = [...used,s]; 29 | if (s === remaining) { 30 | if (x.length < bestSoFar) 31 | bestSoFar = x.length; 32 | yield x; 33 | } 34 | else { 35 | var y = pool.slice(n+1); 36 | yield* distribute(x, y, amount); 37 | } 38 | } 39 | } 40 | 41 | function expected(part) { 42 | return part == 1 ? 10723906903 : 74850409; 43 | } 44 | 45 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2015/25/input.txt: -------------------------------------------------------------------------------- 1 | To continue, please consult the code grid in the manual. Enter the code at row 2978, column 3083. -------------------------------------------------------------------------------- /2015/25/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | if (part === 1) { 3 | let code = 20151125; 4 | for (let d = 1; ; d++) { 5 | for (let c = 1; c < d+1; c++) { 6 | let row = d - c + 1, col = c; 7 | if (row === 2978 && col === 3083) 8 | return code; 9 | code = (code * 252533) % 33554393; 10 | } 11 | } 12 | } 13 | return 0; 14 | } 15 | 16 | function expected(part) { 17 | return part == 1 ? 2650453 : 0; 18 | } 19 | 20 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2017/01/input.txt: -------------------------------------------------------------------------------- 1 | 9513446799636685297929646689682997114316733445451534532351778534251427172168183621874641711534917291674333857423799375512628489423332297538215855176592633692631974822259161766238385922277893623911332569448978771948316155868781496698895492971356383996932885518732997624253678694279666572149831616312497994856288871586777793459926952491318336997159553714584541897294117487641872629796825583725975692264125865827534677223541484795877371955124463989228886498682421539667224963783616245646832154384756663251487668681425754536722827563651327524674183443696227523828832466473538347472991998913211857749878157579176457395375632995576569388455888156465451723693767887681392547189273391948632726499868313747261828186732986628365773728583387184112323696592536446536231376615949825166773536471531487969852535699774113163667286537193767515119362865141925612849443983484245268194842563154567638354645735331855896155142741664246715666899824364722914296492444672653852387389477634257768229772399416521198625393426443499223611843766134883441223328256883497423324753229392393974622181429913535973327323952241674979677481518733692544535323219895684629719868384266425386835539719237716339198485163916562434854579365958111931354576991558771236977242668756782139961638347251644828724786827751748399123668854393894787851872256667336215726674348886747128237416273154988619267824361227888751562445622387695218161341884756795223464751862965655559143779425283154533252573949165492138175581615176611845489857169132936848668646319955661492488428427435269169173654812114842568381636982389224236455633316898178163297452453296667661849622174541778669494388167451186352488555379581934999276412919598411422973399319799937518713422398874326665375216437246445791623283898584648278989674418242112957668397484671119761553847275799873495363759266296477844157237423239163559391553961176475377151369399646747881452252547741718734949967752564774161341784833521492494243662658471121369649641815562327698395293573991648351369767162642763475561544795982183714447737149239846151871434656618825566387329765118727515699213962477996399781652131918996434125559698427945714572488376342126989157872118279163127742349 -------------------------------------------------------------------------------- /2017/01/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | const nextChar = (ch,n) => ch[(n + 1) % ch.length]; 3 | const halfWay = (ch,n) => ch[(n + (ch.length / 2)) % ch.length]; 4 | return sumMatching([...input[0]], part === 1 ? nextChar: halfWay); 5 | } 6 | 7 | function sumMatching(chars, fn) { 8 | return chars.map((c,n) => c === fn(chars,n) ? Number(c) : 0).reduce((a,b) => a+b); 9 | } 10 | 11 | const expected = part => part === 1 ? 1343 : 1274; 12 | 13 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2017/02/input.txt: -------------------------------------------------------------------------------- 1 | 6046 6349 208 276 4643 1085 1539 4986 7006 5374 252 4751 226 6757 7495 2923 2 | 1432 1538 1761 1658 104 826 806 109 939 886 1497 280 1412 127 1651 156 3 | 244 1048 133 232 226 1072 883 1045 1130 252 1038 1022 471 70 1222 957 4 | 87 172 93 73 67 192 249 239 155 23 189 106 55 174 181 116 5 | 5871 204 6466 6437 5716 232 1513 7079 6140 268 350 6264 6420 3904 272 5565 6 | 1093 838 90 1447 1224 744 1551 59 328 1575 1544 1360 71 1583 75 370 7 | 213 166 7601 6261 247 210 4809 6201 6690 6816 7776 2522 5618 580 2236 3598 8 | 92 168 96 132 196 157 116 94 253 128 60 167 192 156 76 148 9 | 187 111 141 143 45 132 140 402 134 227 342 276 449 148 170 348 10 | 1894 1298 1531 1354 1801 974 85 93 1712 130 1705 110 314 107 449 350 11 | 1662 1529 784 1704 1187 83 422 146 147 1869 1941 110 525 1293 158 1752 12 | 162 1135 3278 1149 3546 3686 182 149 119 1755 3656 2126 244 3347 157 865 13 | 2049 6396 4111 6702 251 669 1491 245 210 4314 6265 694 5131 228 6195 6090 14 | 458 448 324 235 69 79 94 78 515 68 380 64 440 508 503 452 15 | 198 216 5700 4212 2370 143 5140 190 4934 539 5054 3707 6121 5211 549 2790 16 | 3021 3407 218 1043 449 214 1594 3244 3097 286 114 223 1214 3102 257 3345 -------------------------------------------------------------------------------- /2017/02/solve.js: -------------------------------------------------------------------------------- 1 | const {max,min} = require('../../utils/utils') 2 | 3 | function solve(input, part) { 4 | const spreadsheet = input.map(r => r.split('\t').map(s => Number(s))) 5 | return checksum(spreadsheet, (part === 1) ? greatestDifference : findDivisors); 6 | } 7 | 8 | const greatestDifference = r => max(r) - min(r) 9 | const checksum = (spreadsheet, rowFn) => spreadsheet.reduce((a,b) => a+rowFn(b),0); 10 | 11 | function* allPairs(arr) { 12 | for (let x = 0; x < arr.length; x++) { 13 | for (let y = 0; y < arr.length; y++) { 14 | if (x !== y) yield [arr[x],arr[y]]; 15 | } 16 | } 17 | } 18 | 19 | function findDivisors(row) { 20 | for (let[a,b] of allPairs(row)) { 21 | if(a%b === 0) return a/b; 22 | } 23 | throw new Error("no divisors found in row"); 24 | } 25 | 26 | const expected = part => part === 1 ? 50376 : 267; 27 | 28 | module.exports = {solve,expected,checksum,greatestDifference,findDivisors}; -------------------------------------------------------------------------------- /2017/03/input.txt: -------------------------------------------------------------------------------- 1 | 312051 -------------------------------------------------------------------------------- /2017/03/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | const startingSquare = Number(input[0]); 3 | if (part === 1) { 4 | const distanceTo = targetNumber => { 5 | let c = 1; 6 | let nextNumber = () => ++c; 7 | let p = find(n => n === targetNumber, nextNumber) 8 | return Math.abs(p.pos[0]) + Math.abs(p.pos[1]); 9 | } 10 | //console.log(distanceTo(12)) //3 11 | //console.log(distanceTo(23)) //2 12 | //console.log(distanceTo(1024)) //31 13 | return distanceTo(startingSquare); 14 | } 15 | else { 16 | const nextNumber = ([x,y],state) => 17 | [[1,0],[1,-1],[0,-1],[-1,-1],[-1,0],[-1,1],[0,1],[1,1]].reduce((acc,[a,b]) => acc + (state[[x+a,y+b]] || 0), 0); 18 | return find(n => n > startingSquare, nextNumber).n; 19 | } 20 | } 21 | 22 | function find(isTarget, nextNumber) { 23 | let state = { }; 24 | state[[0,0]] = 1 25 | for(let p of numberPlacement(p => nextNumber(p,state))) { 26 | state[p.pos] = p.n; 27 | if (isTarget(p.n)) { 28 | return p; 29 | } 30 | } 31 | } 32 | 33 | // placement of next number R1 U1 L2 D2 R3 U3 L4 D4 R5 34 | function* numberPlacement(nextNumber) { 35 | const dir = "RULD"; 36 | let [x,y] = [0,0]; 37 | let dirIndex = 0; 38 | let dist = 1; 39 | let move = () => { 40 | switch(dir[dirIndex]) { 41 | case "R": x++; break; 42 | case "U": y--; break; 43 | case "L": x--; break; 44 | case "D": y++; break; 45 | } 46 | return [x,y]; 47 | } 48 | for(;;) { 49 | for(let q = 0; q < 2; q++) { 50 | for(let n = 0; n < dist; n++) { 51 | let nextPos = move(); 52 | yield { n: nextNumber(nextPos), pos: nextPos} 53 | } 54 | dirIndex++; 55 | dirIndex = dirIndex%dir.length; 56 | } 57 | dist++; 58 | } 59 | } 60 | 61 | const expected = part => part === 1 ? 430 : 312453; 62 | 63 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2017/04/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | return countValid(input, part === 1 ? isValid1 : isValid2); 3 | } 4 | const isValid1 = p => isValid(p, w => w); 5 | const isValid2 = p => isValid(p, w => [...w].sort().join('')); 6 | const countValid = (phrases, validator) => phrases.filter(validator).length; 7 | 8 | function isValid(passphrase, wordMap) { 9 | const words = passphrase.split(' ').map(wordMap); 10 | return words.length === new Set(words).size; 11 | } 12 | 13 | const expected = part => part === 1 ? 337 : 231; 14 | 15 | module.exports = {solve,expected,isValid1,isValid2}; -------------------------------------------------------------------------------- /2017/05/input.txt: -------------------------------------------------------------------------------- 1 | 2 2 | 1 3 | 2 4 | -2 5 | 0 6 | 0 7 | -5 8 | 0 9 | -3 10 | -5 11 | -8 12 | -2 13 | -1 14 | -2 15 | -1 16 | -9 17 | -10 18 | 1 19 | -11 20 | -5 21 | -9 22 | -7 23 | -13 24 | -19 25 | -22 26 | 1 27 | 0 28 | -3 29 | 2 30 | -9 31 | -4 32 | -5 33 | -15 34 | -13 35 | -30 36 | -21 37 | -4 38 | 0 39 | -34 40 | 0 41 | -31 42 | 0 43 | -29 44 | -42 45 | -1 46 | 2 47 | -24 48 | -16 49 | -16 50 | -12 51 | -22 52 | -37 53 | -16 54 | -34 55 | -46 56 | -12 57 | -53 58 | -12 59 | -23 60 | -44 61 | -1 62 | -29 63 | -9 64 | -52 65 | -17 66 | -30 67 | -60 68 | -5 69 | -29 70 | -26 71 | -48 72 | -55 73 | -10 74 | 0 75 | -50 76 | -1 77 | -8 78 | 2 79 | -37 80 | -74 81 | -63 82 | -39 83 | -7 84 | -81 85 | -33 86 | -62 87 | -59 88 | -20 89 | -58 90 | -54 91 | -23 92 | -19 93 | -80 94 | -39 95 | 0 96 | 0 97 | -92 98 | -75 99 | -24 100 | 0 101 | -73 102 | -36 103 | -14 104 | 1 105 | -102 106 | -97 107 | -30 108 | -105 109 | -99 110 | -84 111 | -46 112 | -67 113 | -88 114 | -86 115 | -94 116 | -53 117 | -88 118 | 0 119 | -100 120 | -86 121 | -11 122 | -93 123 | -99 124 | -21 125 | -2 126 | -108 127 | -6 128 | 0 129 | -113 130 | -116 131 | -127 132 | -42 133 | -131 134 | -124 135 | -24 136 | -56 137 | -63 138 | -130 139 | -118 140 | -52 141 | -139 142 | -43 143 | -90 144 | -123 145 | -7 146 | -93 147 | -117 148 | -34 149 | -59 150 | -140 151 | -103 152 | -52 153 | -115 154 | -83 155 | -42 156 | -92 157 | -48 158 | -82 159 | -104 160 | -38 161 | -2 162 | -28 163 | -150 164 | -39 165 | -30 166 | -71 167 | -146 168 | -55 169 | -114 170 | -141 171 | -158 172 | -55 173 | -21 174 | -121 175 | -142 176 | -137 177 | -119 178 | -99 179 | -113 180 | -99 181 | -33 182 | -99 183 | -20 184 | -129 185 | -83 186 | -64 187 | -179 188 | -182 189 | -43 190 | -86 191 | -50 192 | -135 193 | -186 194 | -68 195 | -100 196 | -181 197 | -22 198 | -106 199 | -178 200 | -157 201 | -46 202 | -41 203 | -80 204 | -166 205 | -77 206 | -81 207 | -144 208 | -132 209 | -81 210 | -11 211 | -38 212 | -57 213 | -69 214 | -13 215 | -79 216 | -146 217 | -1 218 | -165 219 | -52 220 | -134 221 | -86 222 | -160 223 | -97 224 | -220 225 | -92 226 | -200 227 | -145 228 | -175 229 | -138 230 | -205 231 | -127 232 | -165 233 | -155 234 | -211 235 | -134 236 | -31 237 | -118 238 | -190 239 | -40 240 | -182 241 | -96 242 | -134 243 | -93 244 | -84 245 | -76 246 | -34 247 | -33 248 | -203 249 | -16 250 | -245 251 | -167 252 | -102 253 | -5 254 | -44 255 | -239 256 | -127 257 | -255 258 | -116 259 | -61 260 | -140 261 | -238 262 | -69 263 | -254 264 | -203 265 | -178 266 | -229 267 | -250 268 | -120 269 | -109 270 | -153 271 | -108 272 | -137 273 | -247 274 | 2 275 | -151 276 | -270 277 | -164 278 | -62 279 | -186 280 | -272 281 | -190 282 | -180 283 | -70 284 | -179 285 | -38 286 | -208 287 | -215 288 | -151 289 | -156 290 | -62 291 | -57 292 | -275 293 | -182 294 | -169 295 | -264 296 | -70 297 | -279 298 | -55 299 | -287 300 | -57 301 | -3 302 | -67 303 | -155 304 | -213 305 | -17 306 | 2 307 | -200 308 | -291 309 | -179 310 | -175 311 | -73 312 | -257 313 | -47 314 | -118 315 | -206 316 | -93 317 | -293 318 | -199 319 | -102 320 | -118 321 | -188 322 | -66 323 | -288 324 | -21 325 | -204 326 | -80 327 | -237 328 | -175 329 | -297 330 | -235 331 | -168 332 | -262 333 | 2 334 | -162 335 | -95 336 | 1 337 | -286 338 | -318 339 | -9 340 | -213 341 | -159 342 | -127 343 | -175 344 | -266 345 | -240 346 | -268 347 | -245 348 | -196 349 | -281 350 | -86 351 | -202 352 | -127 353 | -144 354 | -157 355 | -333 356 | -122 357 | -230 358 | -182 359 | -38 360 | -296 361 | -12 362 | -224 363 | -123 364 | -40 365 | -6 366 | -324 367 | -135 368 | -289 369 | -85 370 | -179 371 | -37 372 | -58 373 | -125 374 | -228 375 | -124 376 | -250 377 | -73 378 | -35 379 | -286 380 | -267 381 | -257 382 | -348 383 | -83 384 | -3 385 | -98 386 | -99 387 | -273 388 | -118 389 | -310 390 | -23 391 | -299 392 | -96 393 | -51 394 | -273 395 | -79 396 | -112 397 | -355 398 | -48 399 | -219 400 | -10 401 | -103 402 | -18 403 | -201 404 | -108 405 | -34 406 | -362 407 | -165 408 | -359 409 | -347 410 | -157 411 | -148 412 | -20 413 | -344 414 | -66 415 | -337 416 | -387 417 | -62 418 | -125 419 | -4 420 | -355 421 | -322 422 | -263 423 | -381 424 | -108 425 | -25 426 | -262 427 | -425 428 | -100 429 | -54 430 | -315 431 | -221 432 | -268 433 | -211 434 | -321 435 | -89 436 | -124 437 | -297 438 | -22 439 | -162 440 | -117 441 | -430 442 | -152 443 | -373 444 | -256 445 | -37 446 | -61 447 | -59 448 | -436 449 | -377 450 | -346 451 | -245 452 | -167 453 | -451 454 | -392 455 | -382 456 | -248 457 | -254 458 | -382 459 | -249 460 | -267 461 | -216 462 | -205 463 | -310 464 | -326 465 | -144 466 | -107 467 | -65 468 | -382 469 | -79 470 | -401 471 | -370 472 | -221 473 | -283 474 | -269 475 | -64 476 | -207 477 | -262 478 | -181 479 | -146 480 | -52 481 | -169 482 | -147 483 | -225 484 | -179 485 | -215 486 | -116 487 | -115 488 | -37 489 | -227 490 | -250 491 | -228 492 | -132 493 | -414 494 | -425 495 | -230 496 | -224 497 | -319 498 | -42 499 | -353 500 | -285 501 | -38 502 | -145 503 | -263 504 | -25 505 | -142 506 | -296 507 | -267 508 | -43 509 | -315 510 | -352 511 | -105 512 | -275 513 | -354 514 | -66 515 | -414 516 | -464 517 | -215 518 | -107 519 | -267 520 | -394 521 | -10 522 | -27 523 | -315 524 | -286 525 | -113 526 | -454 527 | -400 528 | -468 529 | -245 530 | -18 531 | -427 532 | -479 533 | -281 534 | -43 535 | -29 536 | -15 537 | -371 538 | -127 539 | -371 540 | -251 541 | -343 542 | -267 543 | -355 544 | -271 545 | -68 546 | -454 547 | -532 548 | -264 549 | -513 550 | -170 551 | -484 552 | -85 553 | -329 554 | -389 555 | -317 556 | -382 557 | -535 558 | -169 559 | -395 560 | -53 561 | -429 562 | -394 563 | -465 564 | -250 565 | -419 566 | -434 567 | -84 568 | -130 569 | -229 570 | -496 571 | -336 572 | -388 573 | -412 574 | -123 575 | -502 576 | -205 577 | -367 578 | -224 579 | -40 580 | -551 581 | -99 582 | -394 583 | -321 584 | -515 585 | -260 586 | -410 587 | -518 588 | -22 589 | -23 590 | -259 591 | -397 592 | -306 593 | -199 594 | -157 595 | -49 596 | -298 597 | -176 598 | -564 599 | -271 600 | -6 601 | -297 602 | -514 603 | -432 604 | -455 605 | -192 606 | -95 607 | -447 608 | -237 609 | -571 610 | -543 611 | -229 612 | -405 613 | -282 614 | -235 615 | -380 616 | -25 617 | -603 618 | -335 619 | -94 620 | -533 621 | -463 622 | -396 623 | -421 624 | -393 625 | -588 626 | -376 627 | -152 628 | -328 629 | -460 630 | -90 631 | -315 632 | -533 633 | -207 634 | -590 635 | -100 636 | -588 637 | -574 638 | -259 639 | -183 640 | -522 641 | -424 642 | -272 643 | -341 644 | -443 645 | -217 646 | -143 647 | -26 648 | -196 649 | -632 650 | -520 651 | -606 652 | -277 653 | -176 654 | -547 655 | -564 656 | -444 657 | -228 658 | -223 659 | -115 660 | -200 661 | -616 662 | -576 663 | -398 664 | -157 665 | -78 666 | -586 667 | -12 668 | -650 669 | -239 670 | -152 671 | -20 672 | -366 673 | -100 674 | -478 675 | -666 676 | -247 677 | -105 678 | -230 679 | -218 680 | -48 681 | -238 682 | 0 683 | -387 684 | -660 685 | -542 686 | -189 687 | -339 688 | -577 689 | -527 690 | -273 691 | -565 692 | -230 693 | -578 694 | -147 695 | -106 696 | -373 697 | -513 698 | -8 699 | -465 700 | -66 701 | -408 702 | -351 703 | -357 704 | -119 705 | -251 706 | -626 707 | -81 708 | -575 709 | -542 710 | -193 711 | -219 712 | -189 713 | -635 714 | -77 715 | -517 716 | -608 717 | -309 718 | -716 719 | -712 720 | -287 721 | -67 722 | -312 723 | -334 724 | -584 725 | -687 726 | -488 727 | -612 728 | -42 729 | -180 730 | -726 731 | -235 732 | -606 733 | -538 734 | -470 735 | -477 736 | -504 737 | -278 738 | -24 739 | -435 740 | -610 741 | -540 742 | -646 743 | -503 744 | -151 745 | -350 746 | -43 747 | -699 748 | -459 749 | -516 750 | -424 751 | -343 752 | -297 753 | -460 754 | -592 755 | -30 756 | -614 757 | -125 758 | -425 759 | -180 760 | -73 761 | -550 762 | -361 763 | -390 764 | -380 765 | -518 766 | -418 767 | -305 768 | -326 769 | -84 770 | -675 771 | -320 772 | -557 773 | -486 774 | -457 775 | -414 776 | -69 777 | -228 778 | -683 779 | -610 780 | -188 781 | -608 782 | -480 783 | -225 784 | -186 785 | -374 786 | -256 787 | -672 788 | -145 789 | -323 790 | -453 791 | -252 792 | -214 793 | -600 794 | -49 795 | -652 796 | -593 797 | -93 798 | -42 799 | -101 800 | -600 801 | -422 802 | -146 803 | -191 804 | -474 805 | -725 806 | -568 807 | -572 808 | -498 809 | -506 810 | -702 811 | -120 812 | -210 813 | -340 814 | -482 815 | -210 816 | -666 817 | -520 818 | -647 819 | -219 820 | -435 821 | -455 822 | -814 823 | -304 824 | -610 825 | -224 826 | -95 827 | -425 828 | -456 829 | -761 830 | -339 831 | -256 832 | -793 833 | -49 834 | -317 835 | -274 836 | -374 837 | -620 838 | -730 839 | -130 840 | -128 841 | -420 842 | -315 843 | -47 844 | -92 845 | -467 846 | -269 847 | -563 848 | -495 849 | -501 850 | -32 851 | -755 852 | -774 853 | -154 854 | 1 855 | -685 856 | -657 857 | -38 858 | -727 859 | -428 860 | -293 861 | -68 862 | -203 863 | -850 864 | -775 865 | -545 866 | -740 867 | -683 868 | -728 869 | -502 870 | -520 871 | -44 872 | -53 873 | -826 874 | -555 875 | -539 876 | -291 877 | -435 878 | -673 879 | -865 880 | -114 881 | -467 882 | -679 883 | -598 884 | -611 885 | -566 886 | -606 887 | -320 888 | -124 889 | -430 890 | -240 891 | -85 892 | -549 893 | -847 894 | -481 895 | -444 896 | -792 897 | -695 898 | -405 899 | -427 900 | -292 901 | -533 902 | -91 903 | -5 904 | -546 905 | -181 906 | -156 907 | -488 908 | -29 909 | -17 910 | -572 911 | -510 912 | -663 913 | -321 914 | -177 915 | -516 916 | -85 917 | -829 918 | -109 919 | -236 920 | -876 921 | -141 922 | -427 923 | -180 924 | -576 925 | -45 926 | -178 927 | -6 928 | -236 929 | -381 930 | -638 931 | -144 932 | -391 933 | -739 934 | -43 935 | -898 936 | -896 937 | -395 938 | -280 939 | -712 940 | -127 941 | -823 942 | -130 943 | -783 944 | -324 945 | -29 946 | -136 947 | -941 948 | -816 949 | -712 950 | -120 951 | -639 952 | -209 953 | -522 954 | -618 955 | -205 956 | -557 957 | -153 958 | -451 959 | -280 960 | -214 961 | -683 962 | -134 963 | -329 964 | -403 965 | -156 966 | -645 967 | -194 968 | -811 969 | -377 970 | -161 971 | -620 972 | -920 973 | -225 974 | -632 975 | -543 976 | -658 977 | -864 978 | -137 979 | -928 980 | -616 981 | -728 982 | -145 983 | -182 984 | -879 985 | -595 986 | -598 987 | -409 988 | -934 989 | -23 990 | -58 991 | -301 992 | -427 993 | -599 994 | -562 995 | -373 996 | -656 997 | -360 998 | -783 999 | -68 1000 | -228 1001 | -712 1002 | -912 1003 | -260 1004 | -490 1005 | -588 1006 | -481 1007 | -610 1008 | -615 1009 | -180 1010 | -914 1011 | -960 1012 | -462 1013 | -522 1014 | -782 1015 | -617 1016 | -687 1017 | -477 1018 | -934 1019 | -54 1020 | -201 1021 | -279 1022 | -101 1023 | -27 1024 | -759 1025 | -407 1026 | -187 1027 | -202 1028 | -715 1029 | -488 1030 | -206 1031 | -802 1032 | -737 1033 | -18 1034 | -364 1035 | -325 1036 | -155 1037 | -573 1038 | -536 1039 | -769 1040 | -747 1041 | -669 1042 | -856 1043 | -521 1044 | -24 1045 | -921 1046 | -394 1047 | -726 1048 | -251 1049 | -5 1050 | -533 1051 | -923 1052 | -752 1053 | -28 1054 | -775 1055 | -100 1056 | -801 1057 | -22 1058 | -723 1059 | -383 1060 | -952 1061 | -355 1062 | -1058 1063 | -975 1064 | -975 1065 | -706 1066 | -843 1067 | -75 1068 | -124 1069 | -150 1070 | -98 1071 | -1019 1072 | -195 1073 | -342 1074 | -915 1075 | -------------------------------------------------------------------------------- /2017/05/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | const offsets = input.map(Number) 3 | return countStepsUntilExit(offsets, part === 1 ? () => 1 : n => (n>=3)?-1:1); 4 | } 5 | 6 | function countStepsUntilExit(offsets, updateOffset) { 7 | let currentIndex = 0; 8 | let steps = 0 9 | while(currentIndex >= 0 && currentIndex < offsets.length) { 10 | let skip = offsets[currentIndex]; 11 | offsets[currentIndex] += updateOffset(skip); 12 | currentIndex+=skip; 13 | steps++; 14 | } 15 | return steps; 16 | } 17 | 18 | const expected = part => part === 1 ? 378980 : 26889114; 19 | 20 | module.exports = {solve,expected,countStepsUntilExit}; -------------------------------------------------------------------------------- /2017/06/input.txt: -------------------------------------------------------------------------------- 1 | 11 11 13 7 0 15 5 5 4 4 1 1 7 1 15 11 2 | -------------------------------------------------------------------------------- /2017/06/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | const banks = input[0].split('\t').map(Number); 3 | 4 | if (part === 1) { 5 | return countRedistributions(banks).redistributions; 6 | } 7 | else { 8 | return countRedistributions(banks).loopSize; 9 | } 10 | } 11 | 12 | function findMaxIndex(arr) { 13 | let maxIndex = 0; 14 | for(let n = 1; n < arr.length; n++) { 15 | if (arr[n] > arr[maxIndex]) maxIndex = n; 16 | } 17 | return maxIndex; 18 | } 19 | 20 | function countRedistributions(state) { 21 | let seenStates = new Map(); 22 | let key = state.toString() 23 | let redistributions = 0; 24 | while(!seenStates.has(key)) { 25 | seenStates.set(key, redistributions++); 26 | state = redistribute(state); 27 | key = state.toString(); 28 | } 29 | return { redistributions: redistributions, loopSize: redistributions - seenStates.get(key) }; 30 | } 31 | 32 | function redistribute(banks) { 33 | const maxIndex = findMaxIndex(banks); 34 | // banks = Array.from(banks); - to make the function pure 35 | // redistribute 36 | const amount = banks[maxIndex]; 37 | const addToEach = Math.floor(amount/banks.length); 38 | const extras = amount % banks.length; 39 | banks[maxIndex] = 0; 40 | for(let n = 0; n < banks.length; n++) { 41 | banks[(n + maxIndex + 1) % banks.length] += addToEach + ((n < extras) ? 1: 0); 42 | } 43 | return banks; 44 | } 45 | 46 | const expected = part => part === 1 ? 4074 : 2793; 47 | 48 | module.exports = {solve,expected,redistribute,countRedistributions}; -------------------------------------------------------------------------------- /2017/07/solve.js: -------------------------------------------------------------------------------- 1 | const solve = (input, part) => ((part === 1) ? part1 : part2)(input); 2 | 3 | const part1 = input => findRoot(buildTree(parseInput(input))).name; 4 | 5 | function part2(input) { 6 | const root = findRoot(buildTree(parseInput(input))); 7 | return findUnbalancedNode(root).correctWeight; 8 | } 9 | 10 | function findDifferentIndex(arr) { 11 | let n = arr.findIndex(w => w !== arr[0]) 12 | if (n < 0) return [-1]; 13 | return (n === 1 && arr[n] === arr[arr.length - 1]) ? [0,n] : [n,0]; 14 | } 15 | 16 | function findUnbalancedNode(node) { 17 | if (node.children.length === 0) return; 18 | for(let c of node.children) { 19 | let unbalanced = findUnbalancedNode(c); 20 | if (unbalanced) return unbalanced; 21 | } 22 | 23 | let weights = node.children.map(getNodeWeight); 24 | let [differentIndex,correctIndex] = findDifferentIndex(weights); 25 | if (differentIndex < 0) { // all same 26 | return; 27 | } 28 | else { 29 | let difference = weights[differentIndex] - weights[correctIndex]; 30 | let differentNode = node.children[differentIndex]; 31 | //console.log("different", node.name, differentNode.name, differentNode.weight, difference, weights, differentIndex,correctIndex) 32 | return {differentNode,correctWeight:differentNode.weight - difference}; 33 | } 34 | } 35 | 36 | const parseInput = input => input.map(x => 37 | /(\w+) \((\d+)\)( -> ([\w, ]+))?/.exec(x)) 38 | .map(g => ({name:g[1],weight:Number(g[2]),children:g[4]?g[4].split(', '):[],parents:[] })) 39 | 40 | function findRoot(programs) { 41 | return programs.find(p => p.parents.length === 0); 42 | } 43 | 44 | function getNodeWeight(node) { 45 | return node.weight + node.children.reduce((a,b) => a + getNodeWeight(b),0) 46 | } 47 | 48 | function buildTree(programs) { 49 | let nodes = new Map(programs.map(p => [p.name,p])); 50 | 51 | for(let p of programs) { 52 | p.children = p.children.map(c => nodes.get(c)) 53 | for(let c of p.children) { 54 | c.parents.push(nodes.get(p.name)) 55 | } 56 | } 57 | return programs; 58 | } 59 | 60 | const expected = part => part === 1 ? "xegshds" : 299; 61 | 62 | module.exports = {solve,expected,part1,part2,findDifferentIndex}; -------------------------------------------------------------------------------- /2017/08/solve.js: -------------------------------------------------------------------------------- 1 | let { max } = require('../../utils/utils') 2 | 3 | function solve(input, part) { 4 | const instructions = input.map(parseInstruction); 5 | const {largest,registers} = executeInstructions(instructions) 6 | return (part === 1) ? max(registers.values()) : largest; 7 | } 8 | 9 | function parseInstruction(instruction) { 10 | const g = /(\w+) (\w+) (-?\d+) if (\w+) ([<>=!]+) (-?\d+)/.exec(instruction) 11 | return { action: {reg:g[1], op:g[2], amount:Number(g[3])}, test: {reg:g[4], op:g[5], amount:Number(g[6])} }; 12 | } 13 | 14 | function executeInstructions(instructions) { 15 | const registers = new Map(); 16 | let largest = 0; 17 | const applyOpToReg = ({reg,op,amount}) => applyOp(registers.get(reg) || 0, op, amount) 18 | for (let {action,test} of instructions) { 19 | if (applyOpToReg(test)) { 20 | let newValue = applyOpToReg(action) 21 | largest = Math.max(largest,newValue) 22 | registers.set(action.reg, newValue); 23 | } 24 | } 25 | return {largest,registers}; 26 | } 27 | 28 | const ops = {'<':(a,b)=>a':(a,b)=>a>b,'<=':(a,b)=>a<=b,'>=':(a,b)=>a>=b,'!=':(a,b)=>a!==b,'==':(a,b)=>a===b,'inc':(a,b)=>a+b,'dec':(a,b)=>a-b }; 29 | const applyOp = (val,op,amt) => ops[op](val,amt) 30 | 31 | const expected = part => part === 1 ? 4877 : 5471; 32 | 33 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2017/09/input.txt: -------------------------------------------------------------------------------- 1 | {{{{{<>},{{},!!!!!>!>},<,!!o>},{}},{},<{!!a!a!!!!,!{i!!!>>,{>}}},{{{{{<<{!>,,},,}e>}}},{{},},},,<>},{}},{{{{{<}i>,{{}}},{},},<<,!!a'}{"!!!!!>"'u!>,'>,{{!>!!!>,}'u,!{!>,<}!>},<}u>}}}},{<{!"}!>!!u!>},},},{<"{>,{{<>}}}},{{<{!,>},{,{<>}},{{},{{,i!!!>o!!!>>}}}},{{},{{{},{!>u<"'o"'!}!>,,<"ea,{!>,"ei!!}}},{eauu'>}}},{{{ou!>,u>,{!!{>}},{}}}!!!>}>,<"!!'}},{{},{}}}},{},{{{<>},}},{{,!!!!}i"!>e}!{!>},e>},{{},{}}},{}}},{{{{{}},{u>}},{{},{{},}}},{{{<{o!!!>},},!>},,{}},{{!a!!!>e"o}!!!>,>}}},{{{<'!>!"!!!>'a<}i"!>!!>}}},{'>,{{!!,<>}}}}},{{<}!>,<}u!>,<,!!!>{'!!!>!!>,!>,},<}!>,},<{ia}!!a},{<<>,<>},{{{<},<}'!!'>}},{{<'!>},<{!!i,u{!>},<}'!>!!!,}>},{"e!>,!>,i!>,<'>}},{{,<},,!>!o}}}},{{{<,!!!!!>!>,""!>!{'o!!"'!!!>'>,{<}!!!>},},,},<{!!}}}},{{,{!!,<>}},{{,,'!i!>},,<>,},},{,{}},{{{,!>,<'u!!i!}!>},<>,,!!!>i!>}"!>,},<},{,!>!!!"!>,,'!>,"!>!!!"e>}}}},{,u"<'!>!!!>,'>,{{a!!!>"!<>}}}}}},{{{<>}}},{{{{!>},},>,,{!>,<'!o>}},{{{{<},a!!u>}},{{{{},{e>,{,<}!!!!"oo>}}},{{<{!>,<'!!!>,uo!!!!}!!ia!!!!!!!>',o{>}}},{{}}},{{<,'!!!ie!!!!"ea!>},<"a!>{},<>},{>}}},{{{},},,{{}}},{{},{}},{{{},{!!i!><'"!!ia!a>}},{,{<{!!eue{>}}}},{},{{!i},'!!o!!'a>}},{{{{{}i!>,,},{{{},,<,'}e"!>!>i!a}}}},{}},{{{,},<'}!!!>e!!!!!>eo>}},}}}},{{{{,{{,,!>!>u<}!"!!!>!>>}}},{{},<,i{!!!}{!!!>},},!!!>>}},{<{"!!,,{o!{>,{,u'!!o!>},<>}},{}},{{{'!>e,!!a{'!>!>!!!>!>},<>,{{'}}},{,,<},},,},<<}>}},{{!>,},<{!>},}},{{,{<}>,<'<>}}}},{{{},},<">},{{},<"a!!!!!{e!!>}}}},{{{{}},{{{<}!iu!!!!!u,<"a!!!>ea}!>},,<}>},},,!!!>ue>},{{}}}},{{{,!>'!!e}!!!!>!>,i'"!!!>{>},!!!'!!!>>}}}},{{{<"'>}}},{{!!!>,,{<}!!!>!>,<',{>}},{{{{},},<,e}!!"!!!>!>},},!!!!,!>!>},<{!!!>},},e!!o>},!!oe!!!>!!!>,<>}},{{},{{!!uiiae'!!'!>},>},{,,},>}}}}}},{{{{{<}>}}},{}},{{{{{<{!uu',<>}},!>'}!>a<,!>},,<,a>}},{{,},,!!i!oa!!!!!>,!!!>,,>},{{{<,ee>}}}}},{{},{}}}},{{{{{{<,u!!!>!!ai'},{}},{{{},<'!!a!,!>},!!!>},},{{,<>,},}!!!!!>a!!!,!>{!!u!!e}>},!'!!!>u'{',>},{{,}}}},{{{{<'},{""!>,<}"!!!>'}>,{{<"!,!!!!!o,i!!!>>},e!!o!!!>,!!o"''>}}},{}},{{<>},<}"}!!!>e!>,}!>,<"!!!>io>},{{{},},},!ao!>,}}},{{{}}},{{},{<"o!>},"uo!o}!>i!>,<{>,">},{{},{{<"!!a!>,,{{<,{,!!!>>}}},}u"u'!>},<}!!!!!>!>,>},{{}}}}},{{{,<{{{uo"!>,e>},<>}},{{{}},{!>!i!>!!!>,<{!>!!ao>}},{{{<}}"!>,<,!u!{u'!<>},{},},<>}},{,<{"}!!!>e!!!>}ea!!!>'uia,{'o>,{}},{{{<'!!"!!i}!{!!{,>}},{{}}}}}},{{{{{{<,},{{ii!>,},<,'u!!u>},{{,},{<"!>,}!!!>!!}e!!i}}},{{{<{!>}u!!,!>},,,<>},{{!!!>>}}},}},{{},<}u}{i"!!o{,<'a>},{}},{{{<>},{{{u!e<>},i!>!>},<>},ai!>,<>}}},{{{{e!}}!>"!!!!!>!!',<>},{<}},{{{},{{},{},,<{'!!!!!!!>ioa'">}}},},},<,<}u!>},<,!>,!''>}},{{{<>}},{{<'"!!!>},!,!!a",!>!>,,},<"!a<'!>,,<"e!!!>!>o>}},{{},<},>,{}}}},{{'e>},{{},{{}},{{!!!!!>},<>},{<>}}}}},{{{{{},<}u!>,<",!!u!>,},<{{!>},,,<{!>,,!>>}},{},!>,,{}}},{{{<">,<"!o,i,!,>},{ie!>,<"uu!!!>,},i>,},{!>},!>},{!{!>},}},{{!!!>,<'!>},!>,<},},{{{}},},{{{},u>},{<,{'!!!>,>}}}},{{{<'!!',<{!>,,!>},<>,{<,{!!!>!>},<>}},{}},{{{{{,{!>,<,}!,}u{!>},,}},<>},<,{!!"o!>,},{{<{!o,},<,io!!i!!!!!>e{!!!>>},<>},{},<>,{,},''!{!a!!!}!>!!>}}}},{}}},{{{{<,!!!>"ei"'}o!>!!!>o{!!!>e>},{{}}}},{{{}},{{{{{}},<{{!>},,<,!!ii!>,},<>},<,}o"!!>},{<'!!,!!!!!>u>},{{{},<"""{!!!>'">},}},{{{{{ii>,{{u!"uu!!!>!>}!"!!!>!>>},!>,<>}}},{{{},<>},{}}},{{{{{<'!!!>"!!!!"}!>,<{!!!>>},ea"a!!!!oua},<'e!>},<>},<"u{o},!!{>}}},{{{u}}}},{{{{{<''!!!>!>},<>},ae>}},{{{{{{}}}}},{<"!!i,>,{{!>},<{!>},<"!!!>>},<,}!>,<{!eia}!>},!>!>},<"{a!!>}},{<}!!"!!!>uu'!>,<>,{,<>}}},{{},{<>},{!>,<>,!!!>},,}}},{{,"!>,,<"o!!i,,>},{{<"}"{'oi},>}}},{{{{{},{,},<{e!>},,}},{>}},{{,,!!!>>,<'e"!!a!!{!>!!,"e!!!!!!!>,<',!!!>!!!'>},{{},!!ui!!!>,<,},{<}>,{{<{!>,,},<{!!!>!!a!!!>,!!!>>}}}},{{!>{<>,{,!>,<>}},{{},{{},<},a"!!!>u>}},{},!!!>}e!>,,{{}}}}},{{{{{!>},}!!aa{!>,>},,<'i}!!!>!>,<>}}},{{{},<'},},<!!!'e!!>}},{{{{},,<'!>,!><{!uu!!a},,uu!>,<>},{}},{{},a!!ei!{!!>},{{<"!>!>},},<}>}},{{<},},<>,{{{},!!,e!>},<{!>,!!e<>,{<,{!!,i!aoi!>,!>},<,e!!!!u!!!>'e!>>}}},,e{!!!>!{!!!>}ou}},{{},e!!e!>!>,<,!!ua!!e!!!!!>},}}}}},{{{<,!>,},,,},<'!!!>u!>,<>},{{a'!>},<,>},{}},{{,!>,<,!>},,},},},}}},{{{,},!!u'!>,<,!>,}},{}},{{{{!>o{!>"!{!>,"!!}o!!i!>,>}},{{{<}{!a!>},},},}}},{{,!!!>!!!>!!u!}!o>},{,}}},{{{},{},},},>}}}}},{{!u!!!>!>},,>},{{,},<'!!!!!>ea!!!>u!>,e!!!>!oai<>}},{,<'"}!!!!!''iiu!!o'<,!!o'!!u!!!>>}}},{{{},{!}!!!>},{e,},}},{,u!!!>!>},{!ou>},{{},<>},<}ao}>}}}},{{{{"!>,<"o!>},<,}u>},{}},{<}{!>},"!'!>},},,<}{o!!e>}},{{{{<>,'!!!>},},,},,},}},{>,{",'>}},{{},}}},{{,},<"{}a!{ea,'o!>,},},{{o!>,},{!>,!>},<{!!"!!}!!},!><'}},{}}},{}},{{{{},{},!'}a>}}},{{{<"!!{>},{<'!!!>!>,!!!>!!,e!!"',o">,a,,}},{{},{<{!!!!!>!!!!!>,!>{!,!>,<>,},{{{{}},{},{{<>}}},{{}},{{{}},{{}},{{}}}}},{{{{{},oae!!!>!>,}},{{},{}}}},{},{{{{,<'{{!>,!!!!}!>,e,i,<"!!{}!>,},<}}},{{!>e!>,<{ao">},{}},{{},},{},,<"'u'!!!>u}!>,<>}}}},{{{,},},},,o}>},{},{{},'}a,!!!!!>},{u,!>>}},{{{{{!!!!!!o,},!!!>!>o!>,'!>,<>},{}},{!!!>!u,!!!>!>},<">},{<}}!!!>'u!!!!!>}!!!u{"!!o<<>,<>}},{{{},<>}},{{{"!>,,,,},{{,!!'>,,<>}},{},"!e!>!>,},<>}},{{,,!>,<>,{}},},{{ei{}!!'i!!{{{o!e!><>}}}}},{{{{!>!!!!>},{{{{},,!>!>},<,!!{eu'}>}},},<{o!>}!>,<"!!!!!>>},{<>,{},<}>}}}},{a}u!>},},<<"o!>,<}!ue!>o,!<>},{{<{,{!!{a!>},<'!!!!!>!!e!>!>},,<>},{,'{!!!>!!!>!>!>,<}>}}},{{{},}},{,!!,{!!!>!!a}!>,<'u!"{{u>},{{{{}},{{{},{<"ou!>},<'!!!>},!!!>"!>},<>}}}}}},{{},<}!!!>o!!,}}}},{{{{},{,<{>,,<{!!!"e!!!!!!},!a"!eii>},{<!>},uu!"'>}},{{{{},i'!>,}i}>,{}},{{{a!a<},{}},{'!>},!!{a{!>},>}},{}}},{{{uo!>!>'iua!!!<<>,{{},{}}},{{},<>},{!!'!!!>,,<{!o,au!!ooa>}}},{},{{{{<{ia!!''!!i,>},<,!!!>!!!>!e!!!!u!!}",e}aaa!!!>}'a>},{{}},{}},{}}},{{{!>},,>,{},<}o!>,},},},,!!},>}},{{!>},},,,{iaaa<}u!>}!!!!!!>}},<"!>},,},!!!>!>iau">},{{{}},{<,}{iaue,>,{}e!>,<"!!!!!"!>},}}}},{{{<{{}e!!!>!!!>!!>,{!!!>,<<{!{ioai!>,}},{{},<<<,!!i<>},{,<'u!>,}}},{<}eo"!!o'">,{<,'!>!!!>i!!!!>i!!!>!!!>},>}},{{eee!}i!>'"e''!!oa!!!!}!u>}}},{{!>,{!!!>},},},!o>},{{!>,!!a!!!>},<>}}}}},{{{{}}},{{},<"!!ie!>!>'!!eae{i<,i,!>},<>},,},<>}}},{},{{{{<}>},{{{u!"'au{!!e"!!!>!!!>!!!><'>}}}},{{{},},<>},{{}}},{{<{!e"!!!>{>},{{{<{!>e>}}}}},{{{{{{<,,!>},<'i!>},,},},<{e!>e!u,>},{},,<'!o,!,"}i!!!>},<>}},{},!!<},},,<{{!!!!!o>}},{{<{!!<}aiu!!e!!{}}},{{},{{o!!i},>,{{{<<{!>!>!!!!e!'o{!!!>!!'!o"e>},{},<,'a{i'!!!!>}}}}},{{,!!<,!>},,<'oi"!!!>"o,,>},{<"!,!>},<>}}},{{{{,<,u!!<>}}},{!!a!!!>},!!!!!!!!o>}},{{{{<}i}"a!!!>>},{}},{{{!>},o'ie>,<,a,!!!!!>!!!!{o!!,!!!>,{}!!!>,>}}},{{<,ue!!!>'"o!!"!>,},{},},<}!!!>!>,a!>},<>}}},{{<,o!!>},{{<'o!>},!!,}>}},{{,!!!!>,{}},{}}},{{{,},<}!!,{}e,!o!!!>},<}ea{>}},{{{},{,,!!oa{!!}'>}},{{}},{{},{{{{},{,!>},>}},<!!'u<,ie!>!!!>{<<">}}}},{{{{{},<>}},{,,<}'{e!!u'''!>{"}>,{<{o"!!!>}!>},<,!}{!>!>!!a<">}}},{}},{{<'!!}<>},{,<{">,<>}},{},},<{{e!!!>e!>!!!!!>'!>,<'>,{{{,{},,<'ei!>,<,,<,!>,<,>}},{!>!,ui}ae!>o<,i>}},,<'!!!!e!ii>}}}}},{{<'!!!>},,},},{}}},{{{{{}},{}},{{{'!!,},<{>,<,!>,,<}e!!!>!!!!o'}!>,u>}},{{!>e!>},,<}a'>},<{e",!!i!>},<'}>}}},{{{{{{,},<,ai>}}},{{<>,{}}},{{{{}},{{},},},},{}a!>!!i>}},{{<'"o'!!uo!>},<"<>,{u!!!>!'!>!!!>},e!>},<{}}i>,">}},{{<!!"!!!>},<{!!!!}u>,<>},{{{{},!!!>!!,!>"e!!!>!>!!!>i',!!!!>,,},},,!>},<{!}!!!u>},{},{<<'e!>,!!a"{>}}}},{,}}}}}},{{{}},{{{!!!>!>},<}!!{!>a,u!>,}},{{},{{}}}},{{,<>},{{<{!>u!!e!au!>!>,a!!u>,<}!>!>,}}}},{{{i!!!>!>},<>,,<}<'!>},,o'!!e!!e>},{}}},{{{<"!o!!,e"!{u!>},},<'o<>},{!!"aa>}},{{{<">,{}},{{<'}!!!>'!>},<!!"!>,,{,!!{!!u,!!!>>}},{},}},{{{!>!!!>",!!!>},<}}!!!>},},},},,!!!!"!!!>uo!>i<}>}}}}}},{{{,},<<>},{},{}},{{{},{{{},{{,,u>},{{<"}}!!!>,},!!!!!>},a!>,"a!!>},{>}}},{{},<,,<{,eo!!{,<>},{{<>},{{<''a!!!>"'"a!!!>}!>">,!"'!!!>!!ei',!!!>>},{{<{!>,<"!!'!!>}}},{,a!!!>},,,,<{!!a!!,ie,!!">}},{{!!!>},},!!!!!>!!{}a<,'!!!>!!!{>,!e>}}}},{{{},{<{u,!>"o}!>,<"ue!!a,!>!>,<>}}},{{{<"''i'''!!{u<'!!"u{!!a}>},},},},},<"!!!!!>u}o>},{},{{}}},{{{{},{}}},{'!!!>!!>,,<,'!!>},{i,">,{<{}!>,{>}}}},{}},{{},<>,"}!>},<<'a!>,<>},{},{}}},{{{}},{{}!>,},},,<'!>},<>}},{,<>,{{<,},{a{>}}}}},{{{{<">,<},,<"!>a}!!!>uo!{!!!>!!u!!o!i>},{},}},{{{},},{{<'!},!>},<<'"!>!{!i}}},{{<}}ei!!i,{u>}},{{!!!!!>oi"}'e>,<,!!{i>},{}}},{{},{{<>}},{{,<{!>au>},!!a!!}},{{{{'!>i>}},{!}!!'!<>}}}},{{{<,},{{,{<>,{}}}}}},{{{{<'{o!>!!!{u,{,<''a,!>,>}},{{}}},{{{{"!!!>,!>,}!>i!o"!!!!!!!>,<>}}}},{{{!!e!>},},<,!>,},<{e'>},{},{{u!iii!{!!}}}},{{{{>},{{},<{{,i<>}},{{,,!>,<<{!>e}>},}},{{<>,{{!!iu!!}'!>!!!!!>e!>,,<"">}}},{}},{{{<{,e!!!e!!!!!>ei!>'!>},<>,{!"!!!>i!!!>o!>},,<'>}},{{{!">,{}},{}},{},,<,"i}",>},{{{},{<'!!}!!!!!>}!!!!i<,!>,}}}},{{{<>,{}},{{},{,},},{}},{{{!>,i!!!>},>},{}},{{},}i{!>},}}}},{{<}!'}u!>},},<"",!>,,>,{{,,!>},},{<'!!a!"a}o!!!>>}}},{,{}},{}},{,{}}}},{{}},{{},o"!!!!!!!>ai!!!>,<}">},{!>},},,i>}}}},{{{<'!!!!a<,!!!>,!u!!!>},<,>,},},{<"a,'!!">},{{{!!<>},{{},{}}}},{{{<"u"!>},},{<},!!!!e<}'!!'!!""!>'>,{!!!>}}!!!!!>!!"o">}},{{<,!>,!{"!>!!!e'u!>>},{<,a<}"}{!>!!u!>},<>}}},{{{}},{{u>}}},{}},{{{{,!!u'"<<>,{},,},},<>,{a!!uaua,!>},iu>}}},{{},{{{{}},{}},{!>,<",a"!>},,,'>}},{{{!>!>!!!!!>"!>,<>},{}}}},{{},<'!!!>o!},<,eao,>},{{},!!a""!!!!!!!>,<},>},{{e!!!!!!!!!!!>>}}}},{{{{{},{{u!!!>},,},{}}},{{{}}}},{{{{},{<}!!!!i!!!>!>}!>},!}>}}},{,},<"u">,{<}eu">,{}}}}},{{},{{{},},<}!>!!>},{>}},{{<>,{,<},,},<''>}},{{{},<}!>},a!!!>},i!!!>>}},{{{{}},{i!!{au!>,<>}},{{,,,<{,}>}}},{,,{{,<"{!!!>!!a>}}}},{!'!""!>,o"e>,{<"!!>}}},{{{{<},o!!!>!>},<"!!!>>},{}}},{{{}},{{<,"!!!!!>>}}}}},{{}},{{{,,!!!!}'a!!}!>io!!!>!>!>},,<>},{{<},u>},{!!!>{,>}},{},<<>,<'!>!i!>''!!!o,>}},{{{!!!>!>!!!>>}}}},{{{},{{!>},<'i!!!>i>,{o!>},},,,,<{o!>},}},{{<<"e">},{"a!!!>!!o!>,<,u!>},,}}}}}},{{{{{!!u!!!!!!!>,},{,!>,,'!!'!>},<'u'ia>}}}},{{{{,i!>!>},!!!>e,!!!"!>>}}},{{<'!>aa',!!!>i",a>},{<},>}}},{{{<{}e}!'"a!!<'}<,!!!>!>e>,{{<>,{}}}},{<,!!!>!a!!}!>,!''!"i'{>,{o!!aeoi>}},{{{{,e!!"}}},{{,<!>}e>,{}},{}},{,}i{e>}}}},{},{{{,,<'!!{e!!!!!>,!!i{'!<>},{}},{<>,"'}}>}}},{{},{{!>,,},,},!>ae}!>,<,,!o>},{{>}}}}},{{{,<'e!!}!>,!>e!>},,{<},<'ai!!!>!>},oe!>,},<">}}},{{{'a!!!>},>},{{},{{,},,},},},!"'!>,,!>>}},{<<>,,i}>}},{{{},{{},o}>},{{}}}},{,},<'!'}!!!>>,<<",ua!!}uu{!>!!!>!!!>!>},<>},{{{{!!!>a{'!!}i<'a<>},},,,,,,},{!>,<{!>},<}>}},{{{{<}!!u>},{},!'!>},!!e!"{!!!i>}},!!!>!>},,},{{},<"i!!,!!!>a'!!a!!a<"{>},{,'}u>}},{}}}},{{{}},{}}}},{{{{a!!!>!}>}}}},{}},{},{{{{{{<{'>},{<"{}!>},{,!>,},>}},{,},<}i!>,,<>}},{{{,<!>,},{}},{,{>,>}},{,<"e!>!!!>},}},{},ii>,<',},<,o}!"!>!>,<<{!>,<}!!!>>},{}},{{{<,!'!>">,},!!!>!"!!!!!>}u,!{!!!>}>}},{<<'!>},,{{!}ui!!!ee!>},i!!!>}!!!>!!!>'{>},{}}}},{{{{{{}},{}},{{<'{{<,!a!>>,{}},{{}}},{{}}},{{{},!>,},{{},<},},},<>},{{},}ou!!!>,<,"a'!>},"!>,}>}}}},{{{{<>},{{,,<"!!!>!!{!e!>},<"e!!{!>,},!!!>}>},{{},{<}>}}}},{{},{{},{}},{{!!!>!!!>!'i,},<>,{<}ua,i"ai>}},{{},,!!!>,<,>},{{},<,<>},{,<>}}}}},{{{i!>,},!>{!>!!!>o!>}}e!>i>,{<>}},{!>>},{},}},{{{!"u!!}u,}i>,"!!!>},},{!!!>o"!>o!!"!!e{}<}!>},<>,},<,{!>},{{"o!>,,,{}},{{>,{e!'}e!!!>},},}},{a!>!a}!<,{}}}}},{}},{{{{{i!>},},>}},{{''!!!>!>},<{,!"e,!!,>,{<"i,!!!>},},'!!!>,!!}!!!>,>}},{{!>'"{!!!>,,<}}"u!!!!!>!!>,<"!!e'!>o!>{e!!!>,},<{>}}},{},{}},{{{{<'!!,{!!!>},},{}},{<{,oi!!!>o}}!>>}},{{!>,<>}},{{{{!>},e!!!!!!!!"u!e>,{{,,,},}}}}}},{{},{{,,<>},{}}},{{{{},,,>}},{{>},{<"!e!>},,i!!!"'!,!>},}}}},{{{!!ui!!''!>},!{!!!>o{>},{{},!!!>e!>!!,{>}}},{},},{!!!!e'{>,"!>u"},!!}u!>,}}},{{{<{a"u!>!"io!!!>e!>},<}u!>},<}!>},},{<'!!"}!oo!{!!!>!!!>!!{!o!>},}},{{{},<"u!>!!>},{{!!!>e!>},},<{!!u{!!!>!o!>},<>,<>}}}},{{{{}}},{{<{!!!>!>},!>ii!>!>,<{"}"!!>,{,},<""u{!>!>},},<{!>,<,}},,!!e,>}}},{{{{},{}}},{{{{{,eu!!o"}o!,u!>,<{!,{'o'e!!{>}}}},{{{>},<{<}e!>>},{{,<,}}!!{{>},<}!!i'!>},<''i!!!>},!!!!ui!!!>,<,!!!>!>,<>},{{},{u!>},>}}},{{},{{},{e!>,!>,<{oi!!>}},{,<{!!!>!>,!>!>},<>}}},{{{<"!!!>o!i!>!u!!<},!e>}},{{!>,},,<,>,{<,"!!,!!,}{o}eo!>,<>}}}}}},{{{,,!!!>'u!ie!>!>},,<"!!>,{<}!!eu<},<,}>}},{{},,,<'e'iei>}},{{>},{<"!!!>,{!!'!!!!!>e!>,,!!{,>,<,}{i!>},},{>},{{<}!!!>!!'i!>,},}}}},{{<''!>,},{,<"!>,<}!>,<<"!>,!!!!!!'oo!!!!!>a>,{}},{{{!>,}}}},{{}},{{{{{{},!>},},<},<}<>},{<">,{iu,e"u!!ao'>}}},{,<}!!u!!}>,<>}},{{{{>}},{<!>},,"!!!!!>},<!!>}}}},{{{{{},},{{},!!!>},<{,!>},}},{{},},},!!!>,!>!>>}}},{{},,e}},{,},{!>,},{{{},<>},{{<{"}!!}{,>,<>},{i!>,,,ae!>},e'>,!>>},{,{ai!!!>!"!>},,}}},{{<"!>o'u!>},!!!!!>!>,},<">,{}},{<{,!!!>!!!!a!!!>!!!>i!>},<>}}}},{{{<>}},{{>},},},,<>}},{{},},<"<{,!!!>,}>,},},!!!>!"!"!>,<>},{{}}}}}},{{{{{},<'u<'{!>i>}},{{!!!>,<>},},{{},<'<<'!!!>"}!!!!o}},{{},,},,a>},!!aa!!,!!!>!>!!'!,,'!>},},<{ea>}}},{{{{!}}!>!!!!!>a"o!>,},!>!!,o>},{{<'{',"{!!!>e!>,!>},<>},{!>a!!'!o>}}},{}},{{,<{>},{{{{,<'a}!!'!!!e'ue!>!>},<,!!!>{>}},},{},<}},{{<>},!!}e<'!!!>!!!>u,!}!>},<>}}},{{{!!!>a<}<>},{<'{>}},{},{{{!!e!>'>}}}}},{{{{!!!>!!!>'>,'i!!}a"},{{,{}},{}}}}}} 2 | -------------------------------------------------------------------------------- /2017/09/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | let [score,garbageChars] = parseInput(input[0]); 3 | return (part === 1) ? score:garbageChars; 4 | } 5 | 6 | function parseInput(input) { 7 | let nestingLevel = 0; 8 | let score = 0; 9 | let garbageChars = 0; 10 | let inGarbage = false; 11 | for(let n = 0; n < input.length; n++) { 12 | let c = input[n] 13 | if(c === '!') n++; 14 | else if(c === '>') inGarbage = false; 15 | else if(inGarbage) garbageChars++; 16 | else if(c === '<') inGarbage = true; 17 | else if(!inGarbage && c === '{') score += ++nestingLevel; 18 | else if(!inGarbage && c === '}') nestingLevel--; 19 | } 20 | return [score,garbageChars]; 21 | } 22 | 23 | const expected = part => part === 1 ? 13154 : 6369; 24 | 25 | module.exports = {solve,expected,parseInput}; -------------------------------------------------------------------------------- /2017/10/input.txt: -------------------------------------------------------------------------------- 1 | 83,0,193,1,254,237,187,40,88,27,2,255,149,29,42,100 2 | -------------------------------------------------------------------------------- /2017/10/solve.js: -------------------------------------------------------------------------------- 1 | const {range,batch} = require('../../utils/utils') 2 | function solve(input, part) { 3 | if (part === 1) { 4 | let state = Array.from(range(0,256)); 5 | let lengths = input[0].split(',').map(n => Number(n)) 6 | let {result} = applyLengths(state,lengths) 7 | return result[0] * result[1]; 8 | } 9 | else { 10 | return toHex(hashString(input[0])) 11 | } 12 | } 13 | 14 | const expected = part => part === 1 ? 20056 : "d9a7de4a809c56bf3a9465cb84392c8e"; 15 | 16 | function toHex(hashBytes) { 17 | let hash = "" 18 | for(let b of hashBytes) { 19 | hash+= ("0" + b.toString(16)).slice(-2) 20 | } 21 | return hash 22 | } 23 | 24 | function hashString(str) { 25 | let start = Array.from(range(0,256)); 26 | let lengths = [...str].map(c => c.charCodeAt(0)).concat([17, 31, 73, 47, 23]) 27 | let currentPos = 0 28 | let skipSize = 0 29 | for(let n = 0; n < 64; n++) { 30 | ({result:start,currentPos,skipSize} = applyLengths(start,lengths,currentPos,skipSize)); 31 | } 32 | let hash = [] 33 | for(let b of batch(start,16)) { 34 | hash.push(b.reduce((a,b) => a^b)) 35 | } 36 | return hash; 37 | } 38 | 39 | function applyLengths(list, lengths, currentPos=0,skipSize=0) { 40 | for(let length of lengths) { 41 | list = reverseSection(list, currentPos, length) 42 | currentPos += length + skipSize++ 43 | } 44 | return {result:list,currentPos,skipSize}; 45 | } 46 | 47 | function reverseSection(list, currentPos, length) { 48 | let out = Array.from(list) 49 | for(let n = 0; n < length; n++) { 50 | out[(n+currentPos)%out.length] = list[(currentPos+length-n-1)%out.length] 51 | } 52 | return out; 53 | } 54 | 55 | module.exports = {solve,expected,reverseSection,applyLengths,hashString,toHex}; -------------------------------------------------------------------------------- /2017/11/solve.js: -------------------------------------------------------------------------------- 1 | // using 3d hex coordinates https://www.redblobgames.com/grids/hexagons 2 | 3 | function solve(input, part) { 4 | const [endPos,maxDist] = followPath(input[0]) 5 | return (part === 1) ? distance(endPos) : maxDist; 6 | } 7 | 8 | const updateState = ([pos,maxdist],dir) => { 9 | const newPos = move(pos,dir) 10 | return [newPos, Math.max(maxdist,distance(newPos))] 11 | } 12 | const followPath = path => path.split(',').reduce(updateState,[[0,0,0],0]) 13 | const move = (from,dir) => lookup[dir].map((v,n) => v+from[n]) 14 | const distance = ([x,y,z]) => Math.max(Math.abs(x),Math.abs(y),Math.abs(z)) 15 | 16 | const lookup = { 17 | "n": [0,1,-1], 18 | "s": [0,-1,1], 19 | "nw": [-1,1,0], 20 | "se": [1,-1,0], 21 | "ne": [1,0,-1], 22 | "sw": [-1,0,1], 23 | } 24 | 25 | const expected = part => part === 1 ? 664 : 1447; 26 | 27 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2017/12/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | //let x =testInput.map(parse) 3 | //console.log(getGroup(0,x)) 4 | //console.log(parse("4 <-> 2, 3, 6")) 5 | let programs = input.map(parse) 6 | if (part === 1) { 7 | return getGroup(0,programs).size 8 | } 9 | else { 10 | //let programs = testInput.map(parse) 11 | let groups = 0; 12 | let inAnyGroup = new Set(); 13 | for(let g = 0; g < programs.length; g++) { 14 | if(!inAnyGroup.has(g.toString())) { 15 | groups++; 16 | let group = getGroup(g,programs); 17 | for(let m of group) { 18 | inAnyGroup.add(m) 19 | } 20 | //console.log(inAnyGroup) 21 | } 22 | } 23 | return groups; 24 | } 25 | } 26 | 27 | const getGroup = (start,programs) => { 28 | let s = new Set() 29 | visit(s, programs[start].to, programs) 30 | return s; 31 | } 32 | 33 | const visit = (visited,destinations,programs) => { 34 | //console.log('visiting', destinations) 35 | for(let d of destinations) { 36 | if (!visited.has(d)) { 37 | visited.add(d) 38 | visit(visited,programs[Number(d)].to,programs) 39 | } 40 | } 41 | } 42 | 43 | const testInput = ['0 <-> 2', 44 | '1 <-> 1', 45 | '2 <-> 0, 3, 4', 46 | '3 <-> 2, 4', 47 | '4 <-> 2, 3, 6', 48 | '5 <-> 6', 49 | '6 <-> 4, 5`'] 50 | 51 | const parse = s => { 52 | let [,from,dest] = /(\d+) <-> ((\d+)(, \d+)*)/.exec(s); 53 | return {from,to:dest.split(', ')} 54 | } 55 | 56 | const expected = part => part === 1 ? 134 : 193; 57 | 58 | module.exports = {solve,expected}; -------------------------------------------------------------------------------- /2017/13/input.txt: -------------------------------------------------------------------------------- 1 | 0: 3 2 | 1: 2 3 | 2: 4 4 | 4: 6 5 | 6: 4 6 | 8: 6 7 | 10: 5 8 | 12: 6 9 | 14: 8 10 | 16: 8 11 | 18: 8 12 | 20: 6 13 | 22: 12 14 | 24: 8 15 | 26: 8 16 | 28: 10 17 | 30: 9 18 | 32: 12 19 | 34: 8 20 | 36: 12 21 | 38: 12 22 | 40: 12 23 | 42: 14 24 | 44: 14 25 | 46: 12 26 | 48: 12 27 | 50: 12 28 | 52: 12 29 | 54: 14 30 | 56: 12 31 | 58: 14 32 | 60: 14 33 | 62: 14 34 | 64: 14 35 | 70: 10 36 | 72: 14 37 | 74: 14 38 | 76: 14 39 | 78: 14 40 | 82: 14 41 | 86: 17 42 | 88: 18 43 | 96: 26 44 | -------------------------------------------------------------------------------- /2017/13/solve.js: -------------------------------------------------------------------------------- 1 | const {sum,any,first,range} = require('../../utils/utils') 2 | 3 | function solve(input, part) { 4 | const firewall = loadFirewall(input) 5 | return (part === 1) ? scoreTrip(firewall,0) : first(range(0),d => !wasCaught(firewall,d)) 6 | } 7 | 8 | function loadFirewall(input) { 9 | return new Map( input.map(s => /(\d+): (\d+)/.exec(s)) 10 | .map(([,d,r]) => ([Number(d),Number(r)]))) 11 | } 12 | 13 | const isCollision = (range,currentTime) => currentTime%(2 * (range - 1)) === 0; 14 | 15 | const scoreTrip = (firewall, delay) => sum(trip(firewall,delay)); 16 | 17 | const wasCaught = (firewall,delay) => any(trip(firewall,delay)); 18 | 19 | function* trip(firewall, delay) { 20 | for(let [depth,range] of firewall) { 21 | if (isCollision(range,delay+depth)) { 22 | yield depth*range; 23 | } 24 | } 25 | } 26 | 27 | const expected = part => part === 1 ? 1612 : 3907994; 28 | 29 | module.exports = {solve,expected}; 30 | -------------------------------------------------------------------------------- /2017/14/input.txt: -------------------------------------------------------------------------------- 1 | oundnydw -------------------------------------------------------------------------------- /2017/14/solve.js: -------------------------------------------------------------------------------- 1 | const {hashString} = require('../10/solve') 2 | 3 | let grid; 4 | 5 | function solve(input, part) { 6 | grid = grid || buildGrid(input[0]); // perf optimize by remembering the grid from part 1 7 | if (part === 1) { 8 | let totalBits = 0; 9 | for(let x = 0; x < 128; x++) { for(let y = 0; y < 128; y++) totalBits += grid[x][y] === '#'?1:0 } 10 | return totalBits; 11 | } 12 | else { 13 | return countRegions(grid); // test input shoud be 1242 14 | } 15 | //console.log(hashString("flqrgnkx-0")[0].toString(2)); 16 | //console.log(hashString("flqrgnkx-1")[0].toString(2)); 17 | //console.log(hashString("flqrgnkx-2")[0].toString(2)); 18 | } 19 | 20 | const countRegions = grid => { 21 | let regions = 0; 22 | for(let x = 0; x < grid.length; x++) { 23 | for(let y = 0; y < grid[x].length; y++) { 24 | if(grid[x][y] === '#') { 25 | regions++; 26 | clearRegion(grid,x,y) 27 | } 28 | } 29 | } 30 | return regions; 31 | } 32 | 33 | const clearRegion = (grid,x,y) => { 34 | if(grid[x][y] !== '#') return 35 | grid[x][y] = '.'; 36 | if(y+1 < grid[x].length) clearRegion(grid,x,y+1) 37 | if(y > 0) clearRegion(grid,x,y-1) 38 | if(x+1 < grid.length) clearRegion(grid,x+1,y) 39 | if(x > 0) clearRegion(grid,x-1,y) 40 | } 41 | 42 | const buildGrid = key => { 43 | let grid = [] 44 | for(let n = 0; n < 128; n++) { 45 | grid.push(expandHash(getRow(key,n))) 46 | } 47 | /*for(let n = 0; n < 3; n++) { 48 | console.log(grid[n].slice(0,8)) 49 | }*/ 50 | return grid; 51 | } 52 | 53 | const expandHash = hash => { 54 | let b = [] 55 | for (let h of hash) { 56 | let m = 0x80; 57 | while(m) { 58 | b.push(m&h ? '#' : '.') 59 | m = m>>1 60 | } 61 | } 62 | return b; 63 | } 64 | 65 | const getRow = (key,row) => hashString(`${key}-${row}`) 66 | 67 | const expected = part => part === 1 ? 8106 : 1164; 68 | 69 | module.exports = {solve,expected}; 70 | -------------------------------------------------------------------------------- /2017/15/input.txt: -------------------------------------------------------------------------------- 1 | Generator A starts with 699 2 | Generator B starts with 124 -------------------------------------------------------------------------------- /2017/15/solve.js: -------------------------------------------------------------------------------- 1 | let {take,zip,count} = require('../../utils/utils') 2 | function solve(input, part) { 3 | const parse = s => Number(/\d+/.exec(s)[0]) 4 | let genAStart = parse(input[0]) 5 | let genBStart = parse(input[1]) 6 | const aFactor = 16807, bFactor = 48271 7 | 8 | if (part === 1) 9 | return countMatch(generator(genAStart,aFactor), 10 | generator(genBStart,bFactor), 40000000); 11 | else 12 | return countMatch(generator(genAStart,aFactor,n=>(n%4)===0), 13 | generator(genBStart,bFactor,n=>(n%8)===0), 5000000); 14 | } 15 | 16 | function countMatch(seq1,seq2,n) { 17 | const comp = ([a,b]) => (a&0xFFFF) === (b&0xFFFF); // brackets are needed! 18 | return count(take(zip(seq1,seq2),n),comp) 19 | } 20 | 21 | function *generator(seed,factor,test) { 22 | let cur = seed; 23 | for(;;) { 24 | cur = (cur*factor)%2147483647 25 | if (!test || test(cur)) yield cur; 26 | } 27 | } 28 | 29 | const expected = part => part === 1 ? 600 : 313; 30 | 31 | module.exports = {solve,expected,generator}; 32 | -------------------------------------------------------------------------------- /2017/16/solve.js: -------------------------------------------------------------------------------- 1 | 2 | function solve(input, part) { 3 | let instructions = input[0].split(',') 4 | .map(i => i.match(/x(\d+)\/(\d+)|s(\d+)|p([a-z])\/([a-z])/)) 5 | .map(([x,a,b,c,d,e]) => ({move:x[0],exA:Number(a),exB:Number(b),spin:Number(c),pA:d,pB:e})) 6 | const start = "abcdefghijklmnop"; 7 | if (part === 1) { 8 | return dance(instructions,start) 9 | } 10 | else { 11 | let cur = start; 12 | let repetitions = 1000000000; 13 | for(let n = 0; n < repetitions; n++) { 14 | cur = dance(instructions,cur); 15 | if (cur === start) 16 | { 17 | let cycle = n+1; 18 | let extras = repetitions % cycle; 19 | //console.log("cycle",cycle,"extras",extras); 20 | n = 0; 21 | repetitions = extras+1; 22 | } 23 | } 24 | return cur 25 | } 26 | } 27 | 28 | let exchange = (state,a,b) => { 29 | let tmp = state[a] 30 | state[a] = state[b] 31 | state[b] = tmp 32 | return state; 33 | } 34 | let spin = (state,n) => { 35 | return state.slice(state.length - n).concat(state.slice(0,state.length - n)) 36 | } 37 | 38 | function dance(instructions, start) { 39 | let s = [...start] 40 | for(let i of instructions) { 41 | switch(i.move) { 42 | case "x": s = exchange(s,i.exA,i.exB); break; 43 | case "s": s = spin(s,i.spin); break; 44 | case "p": s = exchange(s,s.indexOf(i.pA), s.indexOf(i.pB)); break; 45 | } 46 | } 47 | return s.join('') 48 | } 49 | 50 | 51 | const expected = part => part === 1 ? "pkgnhomelfdibjac" : "pogbjfihclkemadn"; 52 | 53 | module.exports = {solve,expected}; 54 | -------------------------------------------------------------------------------- /2017/17/input.txt: -------------------------------------------------------------------------------- 1 | 348 -------------------------------------------------------------------------------- /2017/17/solve.js: -------------------------------------------------------------------------------- 1 | 2 | function solve(input, part) { 3 | let steps = Number(input[0]) // for test 3 4 | if (part === 1) { 5 | let buf = spinFor(2017,steps) 6 | return buf[buf.indexOf(2017)+1] 7 | } 8 | else { 9 | let second = -1 10 | let curPos = 0; 11 | for(let n = 1; n < 50000000; n++) { 12 | curPos = (curPos + steps)%n + 1 13 | if (curPos === 1) second = n; 14 | } 15 | return second; 16 | } 17 | } 18 | 19 | function spinFor(iterations,steps) { 20 | let buf = [0] 21 | let curPos = 0; 22 | for(let n = 1; n <= iterations; n++) { 23 | curPos = spin(buf,steps,curPos,n) 24 | } 25 | return buf; 26 | } 27 | 28 | function spin(buffer, steps, curPos, val) { 29 | const insertPos = (curPos + steps)%buffer.length + 1 30 | buffer.splice(insertPos, 0, val); 31 | return insertPos; 32 | } 33 | 34 | const expected = part => part === 1 ? 417 : 34334221; 35 | 36 | module.exports = {solve,expected}; 37 | -------------------------------------------------------------------------------- /2017/18/input.txt: -------------------------------------------------------------------------------- 1 | set i 31 2 | set a 1 3 | mul p 17 4 | jgz p p 5 | mul a 2 6 | add i -1 7 | jgz i -2 8 | add a -1 9 | set i 127 10 | set p 735 11 | mul p 8505 12 | mod p a 13 | mul p 129749 14 | add p 12345 15 | mod p a 16 | set b p 17 | mod b 10000 18 | snd b 19 | add i -1 20 | jgz i -9 21 | jgz a 3 22 | rcv b 23 | jgz b -1 24 | set f 0 25 | set i 126 26 | rcv a 27 | rcv b 28 | set p a 29 | mul p -1 30 | add p b 31 | jgz p 4 32 | snd a 33 | set a b 34 | jgz 1 3 35 | snd b 36 | set f 1 37 | add i -1 38 | jgz i -11 39 | snd a 40 | jgz f -16 41 | jgz a -19 42 | -------------------------------------------------------------------------------- /2017/18/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input,part) { 2 | const instructions = input.map(i => i.split(' ')) 3 | if (part === 1) { 4 | let sent = -1 5 | runUntilBlocked(interpreter(instructions, 0, n => sent = n, () => undefined)) 6 | return sent; 7 | } 8 | else { 9 | let sent0 = [] 10 | let sent1 = [] 11 | let i0 = interpreter(instructions, 0, n => sent0.push(n), () => sent1.shift()) 12 | let totalSent1 = 0; 13 | let i1 = interpreter(instructions, 1, n => { sent1.push(n); totalSent1++ }, () => sent0.shift()) 14 | do { 15 | runUntilBlocked(i0) 16 | runUntilBlocked(i1) 17 | } while(sent0.length > 0 || sent1.length > 0) 18 | return totalSent1 19 | } 20 | } 21 | 22 | function interpreter(instructions, id, send, recv) { 23 | const registers = new Map(); 24 | registers.set('p',id) 25 | let blocked = false; 26 | let curPos = 0 27 | const getVal = v => isNaN(v) ? (registers.get(v) || 0) : Number(v) 28 | const commands = { 29 | snd : x => send(getVal(x)), 30 | set : (x,y) => registers.set(x,getVal(y)), 31 | add : (x,y) => registers.set(x,getVal(x) + getVal(y)), 32 | mul : (x,y) => registers.set(x,getVal(x) * getVal(y)), 33 | mod : (x,y) => registers.set(x,getVal(x) % getVal(y)), 34 | rcv : x => { let r = recv(); if (typeof(r) === 'undefined') blocked = true; else { registers.set(x,r); blocked = false; } }, 35 | jgz : (x,y) => curPos += (getVal(x) > 0 ? getVal(y) : 1) 36 | } 37 | const execute = () => { 38 | let [ins,arg1,arg2] = instructions[curPos] 39 | commands[ins](arg1,arg2) 40 | if (!blocked && ins != "jgz") curPos++ 41 | if(curPos < 0 || curPos >= instructions.length) throw Error(`program ${id} exited`) 42 | return blocked 43 | } 44 | function showState() { 45 | console.log(`Prog ${id}`, curPos,instructions[curPos],blocked,registers) 46 | } 47 | return {execute,showState} 48 | } 49 | 50 | function runUntilBlocked(interpreter) { 51 | while (!interpreter.execute()) { // 52 | } 53 | } 54 | 55 | const expected = part => part === 1 ? 8600 : 7239 56 | 57 | module.exports = { solve, expected} -------------------------------------------------------------------------------- /2017/19/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input,part) { 2 | const letters = []; 3 | let [x,y] = [input[0].indexOf('|'),0] 4 | let dir = "D", n = 0; 5 | for(;input[y][x] != " ";n++) { 6 | let c = input[y][x]; 7 | if (c >= "A" && c <= "Z") letters.push(c) 8 | 9 | if (dir === "D" || dir === "U") { 10 | if (c === "+") [x,dir] = input[y][x-1] != " " ? [x-1,"L"] : [x+1,"R"] 11 | else y += (dir === "D") ? 1 : -1; 12 | } 13 | else { 14 | if (c === "+") [y,dir] = input[y-1][x] != " " ? [y-1,"U"] : [y+1,"D"] 15 | else x += (dir === "L") ? -1 : 1; 16 | } 17 | } 18 | return part === 1 ? letters.join('') : n; 19 | } 20 | 21 | const expected = part => part === 1 ? "RUEDAHWKSM" : 17264 22 | 23 | module.exports = {solve,expected} -------------------------------------------------------------------------------- /2017/20/solve.js: -------------------------------------------------------------------------------- 1 | const { minBy,nonRepeated,unfold,firstRepeatedValue } = require('../../utils/utils') 2 | function solve(input,part) { 3 | const particles = input.map(p => p.match(/-?\d+/g).map(d => Number(d))) 4 | .map((x,n) => ({ p: x.slice(0,3), v: x.slice(3,6), a: x.slice(6,9),n })) 5 | const addv = (v1,v2) => [v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]] 6 | const dist = v => Math.abs(v[0]) + Math.abs(v[1]) + Math.abs(v[2]) 7 | const tick = ps => { for(let p of ps) { p.v = addv(p.v,p.a); p.p = addv(p.p,p.v); } return ps; } 8 | if (part === 1) { 9 | return firstRepeatedValue(unfold(particles, tick), 300, ps => minBy(ps, p => dist(p.p)).n) 10 | } 11 | else { 12 | return firstRepeatedValue(unfold(particles, ps => [...nonRepeated(tick(ps),p=>p.p.toString())]), 100, ps => ps.length) 13 | } 14 | } 15 | 16 | const expected = part => part === 1 ? 170 : 571; 17 | 18 | module.exports = { solve, expected} -------------------------------------------------------------------------------- /2017/21/input.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 | ##./###/... => #..#/##../.##./#.#. 41 | #.#/###/... => ..#./...#/#.../...# 42 | ###/###/... => ...#/##../...#/#.## 43 | ..#/.../#.. => ##.#/.#.#/.##./###. 44 | #.#/.../#.. => ###./#..#/.#.#/#.## 45 | .##/.../#.. => ...#/.#.#/.###/###. 46 | ###/.../#.. => .#../...#/..#./.#.. 47 | .##/#../#.. => .#../...#/.##./..#. 48 | ###/#../#.. => .###/##.#/#.##/.### 49 | ..#/.#./#.. => ##.#/##../##../#... 50 | #.#/.#./#.. => #.../.###/#.#./#... 51 | .##/.#./#.. => ###./#.##/###./#### 52 | ###/.#./#.. => .#../..##/##.#/##.# 53 | .##/##./#.. => ##.#/##../.##./...# 54 | ###/##./#.. => .#.#/.#../####/.##. 55 | #../..#/#.. => ..##/###./...#/##.. 56 | .#./..#/#.. => .#../...#/.#../..## 57 | ##./..#/#.. => ###./..##/###./.##. 58 | #.#/..#/#.. => ####/.#.#/...#/..## 59 | .##/..#/#.. => #..#/.#../#.##/#### 60 | ###/..#/#.. => .#../#.##/#.##/.#.. 61 | #../#.#/#.. => ..#./#.##/.#../.##. 62 | .#./#.#/#.. => ##../#.../#.#./###. 63 | ##./#.#/#.. => #..#/.##./####/.#.. 64 | ..#/#.#/#.. => ##.#/..#./..#./.#.# 65 | #.#/#.#/#.. => .#../..#./..#./..## 66 | .##/#.#/#.. => ##../#.##/#.#./#.## 67 | ###/#.#/#.. => ##.#/..##/##../##.# 68 | #../.##/#.. => .###/####/#.##/..## 69 | .#./.##/#.. => #.#./.##./###./#.## 70 | ##./.##/#.. => ..#./#..#/####/...# 71 | #.#/.##/#.. => ####/.#.#/##../##.# 72 | .##/.##/#.. => #.#./#..#/.#.#/.##. 73 | ###/.##/#.. => .#../.##./.##./.### 74 | #../###/#.. => #..#/###./##.#/##.. 75 | .#./###/#.. => #.#./#..#/..#./#..# 76 | ##./###/#.. => ..../##.#/####/...# 77 | ..#/###/#.. => ..../#.../##../#..# 78 | #.#/###/#.. => ..#./.#../..../##.# 79 | .##/###/#.. => #..#/###./##.#/.### 80 | ###/###/#.. => #.../.##./#.##/.##. 81 | .#./#.#/.#. => ...#/#.../.#../##.# 82 | ##./#.#/.#. => .#.#/#.#./.#../#.## 83 | #.#/#.#/.#. => #.##/.##./###./.... 84 | ###/#.#/.#. => ##../#..#/#.../.### 85 | .#./###/.#. => ###./#.../.#../#..# 86 | ##./###/.#. => ##../##../#.../#... 87 | #.#/###/.#. => ##../.#.#/#.##/#.#. 88 | ###/###/.#. => #.##/##.#/#.#./#... 89 | #.#/..#/##. => ..../..#./####/..## 90 | ###/..#/##. => #.../...#/#.#./#.#. 91 | .##/#.#/##. => ..##/###./.##./#... 92 | ###/#.#/##. => .#../###./##.#/...# 93 | #.#/.##/##. => .###/##../.###/..#. 94 | ###/.##/##. => .#.#/##.#/.##./.### 95 | .##/###/##. => ..#./.#.#/.#../#..# 96 | ###/###/##. => ###./#..#/####/...# 97 | #.#/.../#.# => .#.#/.#../.#.#/#... 98 | ###/.../#.# => #..#/##../.#../...# 99 | ###/#../#.# => ..../.#../#.../..## 100 | #.#/.#./#.# => #.#./####/.#.#/.##. 101 | ###/.#./#.# => ..#./####/#..#/..## 102 | ###/##./#.# => .##./.#../#.##/.#.# 103 | #.#/#.#/#.# => ##../..##/##.#/#.#. 104 | ###/#.#/#.# => .##./#..#/#..#/.#.# 105 | #.#/###/#.# => ..#./.###/#.##/#.## 106 | ###/###/#.# => ###./###./.#.#/###. 107 | ###/#.#/### => #.##/..##/#..#/...# 108 | ###/###/### => ...#/.#../##.#/.##. 109 | -------------------------------------------------------------------------------- /2017/21/solve.js: -------------------------------------------------------------------------------- 1 | const { flatMap,map,unfold,skip,first } = require('../../utils/utils') 2 | function solve(input,part) { 3 | const rules = input.map(i => i.replace(/\//g,'').split(' ')).map(p => [p[0],p[2]]) 4 | const lookup = new Map(flatMap(rules,([input,output]) => map(expand(input),i => [i,output]))) 5 | const start = [".#.","..#","###"] 6 | const repeats = (part === 1 ? 5 : 18); 7 | let end = first(skip(unfold(start, s=>iterate(s,lookup)),repeats)) 8 | return end.reduce((a,s) => a + s.replace(/\./g,'').length,0) 9 | } 10 | 11 | function iterate(p, lookup) { 12 | let out = []; 13 | if (p.length % 2 == 0) { 14 | let y2 = 0 15 | // 2x2 16 | for(let y = 0; y < p.length; y+=2) { 17 | for(let x = 0; x < p.length; x+=2) { 18 | let key = p[y][x] + p[y][x+1] + p[y+1][x] + p[y+1][x+1] 19 | if (!lookup.has(key)) throw new Error("lookup not found [" + key + "]") 20 | let r = lookup.get(key) // will be 9 length string 21 | 22 | out[y2] = (out[y2] || "") + r.slice(0,3) 23 | out[y2+1] = (out[y2+1] || "") + r.slice(3,6) 24 | out[y2+2] = (out[y2+2] || "") + r.slice(6,9) 25 | } 26 | y2+=3 27 | } 28 | } 29 | else { 30 | // 3x3 31 | let y2 = 0 32 | for(let y = 0; y < p.length; y+=3) { 33 | for(let x = 0; x < p.length; x+=3) { 34 | let key = p[y][x] + p[y][x+1] + p[y][x+2] + p[y+1][x] + p[y+1][x+1] + p[y+1][x+2] + p[y+2][x] + p[y+2][x+1] + p[y+2][x+2] 35 | if (!lookup.has(key)) throw new Error("lookup not found [" + key + "]") 36 | let r = lookup.get(key)// will be 16 length string 37 | out[y2] = (out[y2] || "") + r.slice(0,4) 38 | out[y2+1] = (out[y2+1] || "") + r.slice(4,8) 39 | out[y2+2] = (out[y2+2] || "") + r.slice(8,12) 40 | out[y2+3] = (out[y2+3] || "") + r.slice(12,16) 41 | } 42 | y2+=4 43 | } 44 | } 45 | return out; 46 | } 47 | 48 | const flip2 = s => s[2]+s[3]+s[0]+s[1] 49 | const flip2LR = s => s[1]+s[0]+s[3]+s[2] 50 | const rot2 = s => s[2]+s[0]+s[3]+s[1] 51 | 52 | const flip3 = s => s[6]+s[7]+s[8]+s[3]+s[4]+s[5]+s[0]+s[1]+s[2] 53 | const flip3LR = s => s[2]+s[1]+s[0]+s[5]+s[4]+s[3]+s[8]+s[7]+s[6] 54 | const rot3 = s => s[6]+s[3]+s[0]+s[7]+s[4]+s[1]+s[8]+s[5]+s[2] 55 | 56 | function perms(s,q,ops) { 57 | s.add(q) 58 | for(let op of ops) { 59 | let f = op(q) 60 | if(!s.has(f)) { 61 | perms(s,f,ops) 62 | } 63 | } 64 | } 65 | 66 | function expand(p) { 67 | let s = new Set() 68 | if (p.length === 4) { 69 | perms(s,p,[flip2,flip2LR,rot2]) 70 | } 71 | else if (p.length === 9){ 72 | perms(s,p,[flip3,flip3LR,rot3]) 73 | } 74 | else { 75 | throw new Error("unexpected expand length",p) 76 | } 77 | return s; 78 | } 79 | 80 | const expected = part => part === 1 ? 197 : 3081737 81 | 82 | module.exports = { solve, expected } -------------------------------------------------------------------------------- /2017/22/input.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 | -------------------------------------------------------------------------------- /2017/22/solve.js: -------------------------------------------------------------------------------- 1 | const { flatMap } = require('../../utils/utils') 2 | function solve(input, part) { 3 | //console.log(input.length,input[0].length) 4 | let delta = Math.floor(input.length / 2) 5 | const viruses = new Map([...flatMap(input.map((row,y) => [...row].map((ch,x) => [ch,x-delta,y-delta]).filter(([ch]) => ch === '#')))].map(([,x,y]) => [`${x},${y}`,'#'])) 6 | let curPos = [0,0] 7 | let curDir = 'U' 8 | const dirs = "URDLURDL" 9 | let newInfections = 0; 10 | let bursts = part === 1 ? 10000 : 10000000; 11 | for(let burst = 0; burst < bursts; burst++) { 12 | const key = curPos.toString() 13 | //console.log(curPos,curDir,isInfected) 14 | if (part === 1) { 15 | const isInfected = viruses.get(key) === '#' 16 | curDir = dirs[dirs.indexOf(curDir) + (isInfected ? 1 : 3)] 17 | if (isInfected) { 18 | viruses.delete(key); 19 | } 20 | else { 21 | newInfections++; 22 | viruses.set(key,'#') 23 | } 24 | 25 | } 26 | else { 27 | const states = ".W#F."; 28 | const curState = viruses.get(key) || '.' 29 | if (curState === '.') curDir = dirs[dirs.indexOf(curDir) + 3] // left 30 | else if (curState === '#') curDir = dirs[dirs.indexOf(curDir) + 1] // right 31 | else if (curState === 'F') curDir = dirs[dirs.indexOf(curDir) + 2] // reverse 32 | const newState = states[states.indexOf(curState) + 1] 33 | if (newState === '#') newInfections++; 34 | //console.log(curNode, newState, curDir, curPos) 35 | viruses.set(key, newState) 36 | } 37 | if(curDir === 'U') curPos[1]--; 38 | else if(curDir === 'D') curPos[1]++; 39 | else if(curDir === 'L') curPos[0]--; 40 | else curPos[0]++; 41 | } 42 | //console.log(viruses) 43 | return newInfections; 44 | } 45 | 46 | const expected = part => part === 1 ? 5305 : 2511424 47 | 48 | module.exports = { solve, expected } -------------------------------------------------------------------------------- /2017/23/input.txt: -------------------------------------------------------------------------------- 1 | set b 67 2 | set c b 3 | jnz a 2 4 | jnz 1 5 5 | mul b 100 6 | sub b -100000 7 | set c b 8 | sub c -17000 9 | set f 1 10 | set d 2 11 | set e 2 12 | set g d 13 | mul g e 14 | sub g b 15 | jnz g 2 16 | set f 0 17 | sub e -1 18 | set g e 19 | sub g b 20 | jnz g -8 21 | sub d -1 22 | set g d 23 | sub g b 24 | jnz g -13 25 | jnz f 2 26 | sub h -1 27 | set g b 28 | sub g c 29 | jnz g 2 30 | jnz 1 3 31 | sub b -17 32 | jnz 1 -23 -------------------------------------------------------------------------------- /2017/23/solve.js: -------------------------------------------------------------------------------- 1 | function solve(input, part) { 2 | const instructions = input.map(i => i.split(' ')) 3 | 4 | if (part === 1) { 5 | const int = interpreter(instructions, 0) 6 | while(!int.execute()) { 7 | // 8 | } 9 | return int.mult(); 10 | } 11 | // counting non-primes 12 | let h = 0 13 | for(let b = 106700; b <= 123700; b += 17) { 14 | if (!isPrime(b)) h++; 15 | } 16 | return h; 17 | } 18 | 19 | function interpreter(instructions, a) { 20 | const registers = new Map(); 21 | registers.set('a',a) 22 | let curPos = 0 23 | let multiplies = 0; 24 | const getVal = v => isNaN(v) ? (registers.get(v) || 0) : Number(v) 25 | const commands = { 26 | set : (x,y) => registers.set(x,getVal(y)), 27 | sub : (x,y) => registers.set(x,getVal(x) - getVal(y)), 28 | mul : (x,y) => { multiplies++; registers.set(x,getVal(x) * getVal(y)) }, 29 | jnz : (x,y) => curPos += (getVal(x) != 0 ? getVal(y) : 1) 30 | } 31 | const execute = () => { 32 | let [ins,arg1,arg2] = instructions[curPos] 33 | commands[ins](arg1,arg2) 34 | if (ins != "jnz") curPos++ 35 | return (curPos < 0 || curPos >= instructions.length); 36 | } 37 | function showState() { 38 | console.log(curPos,instructions[curPos],registers) 39 | } 40 | return {execute,showState,mult:() => multiplies} 41 | } 42 | 43 | const isPrime = num => { 44 | for(let i = 2, s = Math.sqrt(num); i <= s; i++) 45 | if(num % i === 0) return false; 46 | return num !== 1; 47 | } 48 | 49 | const expected = part => part === 1 ? 4225 : 905 50 | 51 | module.exports = { solve, expected } -------------------------------------------------------------------------------- /2017/24/input.txt: -------------------------------------------------------------------------------- 1 | 24/14 2 | 30/24 3 | 29/44 4 | 47/37 5 | 6/14 6 | 20/37 7 | 14/45 8 | 5/5 9 | 26/44 10 | 2/31 11 | 19/40 12 | 47/11 13 | 0/45 14 | 36/31 15 | 3/32 16 | 30/35 17 | 32/41 18 | 39/30 19 | 46/50 20 | 33/33 21 | 0/39 22 | 44/30 23 | 49/4 24 | 41/50 25 | 50/36 26 | 5/31 27 | 49/41 28 | 20/24 29 | 38/23 30 | 4/30 31 | 40/44 32 | 44/5 33 | 0/43 34 | 38/20 35 | 20/16 36 | 34/38 37 | 5/37 38 | 40/24 39 | 22/17 40 | 17/3 41 | 9/11 42 | 41/35 43 | 42/7 44 | 22/48 45 | 47/45 46 | 6/28 47 | 23/40 48 | 15/15 49 | 29/12 50 | 45/11 51 | 21/31 52 | 27/8 53 | 18/44 54 | 2/17 55 | 46/17 56 | 29/29 57 | 45/50 58 | -------------------------------------------------------------------------------- /2017/24/solve.js: -------------------------------------------------------------------------------- 1 | const { max} = require('../../utils/utils') 2 | 3 | let bridges; 4 | function solve(input,part) { 5 | let parts = input.map(i => i.split('/').map(n => Number(n))) 6 | bridges = bridges || [...build(0,[],parts,0)] 7 | if (part === 1) { 8 | return max(bridges,c => c.strength) 9 | } 10 | else { 11 | return bridges.sort((a,b) => b.used.length - a.used.length || b.strength - a.strength)[0].strength 12 | } 13 | } 14 | 15 | function *build(cur,used,available,strength) { 16 | for(let [a,b] of available) { 17 | if(a === cur || b === cur) { 18 | yield* build(a === cur ? b : a,[...used,[a,b]],available.filter(([x,y]) => !(x===a && y===b)),strength+a+b) 19 | } 20 | } 21 | yield {used,strength} 22 | } 23 | 24 | const expected = part => part === 1 ? 2006 : 1994; 25 | 26 | module.exports = { solve, expected } -------------------------------------------------------------------------------- /2017/25/input.txt: -------------------------------------------------------------------------------- 1 | Begin in state A. 2 | Perform a diagnostic checksum after 12481997 steps. 3 | 4 | In state A: 5 | If the current value is 0: 6 | - Write the value 1. 7 | - Move one slot to the right. 8 | - Continue with state B. 9 | If the current value is 1: 10 | - Write the value 0. 11 | - Move one slot to the left. 12 | - Continue with state C. 13 | 14 | In state B: 15 | If the current value is 0: 16 | - Write the value 1. 17 | - Move one slot to the left. 18 | - Continue with state A. 19 | If the current value is 1: 20 | - Write the value 1. 21 | - Move one slot to the right. 22 | - Continue with state D. 23 | 24 | In state C: 25 | If the current value is 0: 26 | - Write the value 0. 27 | - Move one slot to the left. 28 | - Continue with state B. 29 | If the current value is 1: 30 | - Write the value 0. 31 | - Move one slot to the left. 32 | - Continue with state E. 33 | 34 | In state D: 35 | If the current value is 0: 36 | - Write the value 1. 37 | - Move one slot to the right. 38 | - Continue with state A. 39 | If the current value is 1: 40 | - Write the value 0. 41 | - Move one slot to the right. 42 | - Continue with state B. 43 | 44 | In state E: 45 | If the current value is 0: 46 | - Write the value 1. 47 | - Move one slot to the left. 48 | - Continue with state F. 49 | If the current value is 1: 50 | - Write the value 1. 51 | - Move one slot to the left. 52 | - Continue with state C. 53 | 54 | In state F: 55 | If the current value is 0: 56 | - Write the value 1. 57 | - Move one slot to the right. 58 | - Continue with state D. 59 | If the current value is 1: 60 | - Write the value 1. 61 | - Move one slot to the right. 62 | - Continue with state A. 63 | -------------------------------------------------------------------------------- /2017/25/solve.js: -------------------------------------------------------------------------------- 1 | const { batch,skip } = require('../../utils/utils') 2 | 3 | function solve(input,part) { 4 | if (part === 2) return 0 5 | let state = input[0].match(/Begin in state (.)\./)[1] 6 | const steps = Number(input[1].match(/after (\d+) steps/)[1]) 7 | let cursor = 0, tape = {}, rules = {} 8 | const parseState = s => s.match(/state (.)/)[1] 9 | const parseVal = s => Number(s.match(/the value (\d)\./)[1]) 10 | const parseDir = s => s.match(/to the right/) ? 1 : -1 11 | for(let b of batch(skip(input,2),9)) { // nb blank input lines already stripped 12 | rules[parseState(b[0])] = [parseVal(b[2]),parseDir(b[3]),parseState(b[4]), 13 | parseVal(b[6]),parseDir(b[7]),parseState(b[8])] 14 | } 15 | 16 | for(let step = 0; step < steps; step++) { 17 | let rule = rules[state]; 18 | [tape[cursor],cursor,state] = (tape[cursor]) ? 19 | [rule[3],cursor+rule[4],rule[5]] : 20 | [rule[0],cursor+rule[1],rule[2]]; 21 | } 22 | 23 | let checksum = 0 24 | for(let p in tape) { 25 | if (tape[p] === 1) checksum++; 26 | } 27 | return checksum; 28 | } 29 | 30 | const expected = part => part === 1 ? 3362: 0; 31 | 32 | module.exports = {solve,expected} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advent of Code JavaScript Solutions 2 | 3 | This is a repository for me to attempt the [Advent of Code](http://adventofcode.com) challenges in JavaScript. 4 | 5 | In past years I've solved them using C# and F#. [read about my solutions here](http://markheath.net/category/advent+of+code). This repository is for me to improve my JavaScript skills by solving the puzzles with node.js as ES6. I've ported my 2015 solutions to JavaScript, and in 2017 I just used JavaScript. 6 | 7 | To get started: 8 | ``` 9 | npm install 10 | ``` 11 | 12 | To solve all puzzles for this year 13 | 14 | ``` 15 | node index.js 16 | ``` 17 | 18 | To run all tests for 2015: 19 | ``` 20 | node index.js 2015 21 | ``` 22 | 23 | To run tests for 2015 day 10 24 | ``` 25 | node index.js 2015 10 26 | ``` 27 | 28 | To run Jasmine unit tests 29 | ``` 30 | npm test 31 | ``` 32 | 33 | To run a subset of Jasmine unit tests 34 | ``` 35 | npm test -- --filter="flatMap" 36 | ``` 37 | 38 | ## Blog posts about 2017 solutions 39 | 40 | - [Day 1](http://markheath.net/post/advent-of-code-2017-day-1) 41 | - [Day 2](http://markheath.net/post/advent-of-code-2017-day-2) 42 | - [Day 3](http://markheath.net/post/advent-of-code-2017-day-3) 43 | - [Day 4](http://markheath.net/post/advent-of-code-2017-day-4) 44 | - [Day 5](http://markheath.net/post/advent-of-code-2017-day-5) 45 | - [Day 6](http://markheath.net/post/advent-of-code-2017-day-6) 46 | - [Day 7](http://markheath.net/post/advent-of-code-2017-day-7) 47 | - [Day 8](http://markheath.net/post/advent-of-code-2017-day-8) 48 | - [Day 9](http://markheath.net/post/advent-of-code-2017-day-9) 49 | - [Day 10](http://markheath.net/post/advent-of-code-2017-day-10) 50 | - [Day 11](http://markheath.net/post/advent-of-code-2017-day-11) 51 | - [Day 12](http://markheath.net/post/advent-of-code-2017-day-12) 52 | - [Day 13](http://markheath.net/post/advent-of-code-2017-day-13) 53 | - [Day 14](http://markheath.net/post/advent-of-code-2017-day-14) 54 | - [Day 15](http://markheath.net/post/advent-of-code-2017-day-15) 55 | - [Day 16](http://markheath.net/post/advent-of-code-2017-day-16) 56 | - [Day 17](http://markheath.net/post/advent-of-code-2017-day-17) 57 | - [Day 18](http://markheath.net/post/advent-of-code-2017-day-18) 58 | - [Day 19](http://markheath.net/post/advent-of-code-2017-day-19) 59 | - [Day 20](http://markheath.net/post/advent-of-code-2017-day-20) 60 | - [Day 21](http://markheath.net/post/advent-of-code-2017-day-21) 61 | - [Day 22](http://markheath.net/post/advent-of-code-2017-day-22) 62 | - [Day 23](http://markheath.net/post/advent-of-code-2017-day-23) 63 | - [Day 24](http://markheath.net/post/advent-of-code-2017-day-24) 64 | - [Day 25](http://markheath.net/post/advent-of-code-2017-day-25) 65 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const fs = require('fs'); 3 | 4 | let year = 2017; 5 | let startDay = 1; 6 | let endDay = 25; 7 | const args = process.argv.slice(2); 8 | for(let arg of args) { 9 | const n = Number(arg); 10 | if (n > 2000) { 11 | year = n; 12 | } 13 | else if (n > 0) { 14 | startDay = n; 15 | endDay = n; 16 | } 17 | } 18 | 19 | const timed = fn => { 20 | const start = process.hrtime(); 21 | const output = fn(); 22 | const [secs,nanosecs] = process.hrtime(start); 23 | const duration = secs*1000 + Math.floor(nanosecs/1000000); 24 | return [output, duration]; 25 | } 26 | 27 | const showTestResult = (year, day, part, expected, actual, duration) => { 28 | const durationDesc = chalk.blue(` (${duration}ms)`); 29 | if (actual === expected) { 30 | console.log(chalk.green(`${year} day ${day} part ${part}: ${actual}`) + durationDesc); 31 | } 32 | else { 33 | console.log(chalk.red(`${year} day ${day} part ${part}: ${actual} - expected ${expected}` + durationDesc)); 34 | } 35 | } 36 | 37 | for(let day = startDay; day <= endDay; day++) { 38 | const path = `./${year}/${("0" + day).slice(-2)}`; 39 | if (!fs.existsSync(path)) { 40 | console.log(chalk.red(`${year} day ${day} not found`)); 41 | break; 42 | } 43 | const solver = require(path +`/solve`); 44 | const text = fs.readFileSync(path + `/input.txt`) 45 | .toString() 46 | .split('\n') 47 | .map(s => s.replace(/\r$/, '')) 48 | .filter(s => s.length > 0); 49 | for(let part of [1,2]) { 50 | const expected = solver.expected(part); 51 | const [answer,duration] = timed(() => solver.solve(text, part)); 52 | showTestResult(year, day, part, expected, answer, duration); 53 | } 54 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aocjs", 3 | "version": "1.0.0", 4 | "description": "Advent of Code JavaScript", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jasmine" 8 | }, 9 | "author": "Mark Heath", 10 | "license": "ISC", 11 | "dependencies": { 12 | "chalk": "^2.3.0", 13 | "lodash": "^4.17.4" 14 | }, 15 | "devDependencies": { 16 | "eslint": "^4.12.1", 17 | "jasmine": "^2.8.0", 18 | "eslint-config-standard": "^10.2.1", 19 | "eslint-plugin-import": "^2.8.0", 20 | "eslint-plugin-node": "^5.2.1", 21 | "eslint-plugin-promise": "^3.6.0", 22 | "eslint-plugin-standard": "^3.0.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /spec/2015/10-Spec.js: -------------------------------------------------------------------------------- 1 | let { groupAdjacent,next } = require("../../2015/10/solve") 2 | 3 | describe("2015 day 10", function() { 4 | it ("can group adjacent", function() { 5 | let solution = groupAdjacent([1,1,1,2,2,3,3,3]) 6 | expect(solution).toEqual([[1,1,1],[2,2],[3,3,3]]) 7 | }) 8 | 9 | const nextNumbers = [ 10 | [ [1], [1,1] ], 11 | [ [1,1], [2,1] ], 12 | [ [2,1], [1,2,1,1] ], 13 | [ [1,2,1,1], [1,1,1,2,2,1] ], 14 | [ [1,1,1,2,2,1], [3,1,2,2,1,1] ] 15 | ]; 16 | 17 | it ("can calc next number", function() { 18 | for (let [s,n] of nextNumbers) 19 | expect([...next(s)]).toEqual(n); 20 | }) 21 | }); -------------------------------------------------------------------------------- /spec/2017-02-Spec.js: -------------------------------------------------------------------------------- 1 | let { checksum,greatestDifference,findDivisors } = require("../2017/02/solve") 2 | 3 | describe("2017 day 2", function() { 4 | it ("solves the part 1 test case", function() { 5 | const part1TestSpreadsheet = [[5,1,9,5],[7,5,3],[2,4,6,8]] 6 | let solution = checksum(part1TestSpreadsheet,greatestDifference) 7 | expect(solution).toEqual(18) 8 | }) 9 | 10 | it ("solves the part 2 test case", function() { 11 | const part2TestSpreadsheet = [[5,9,2,8],[9,4,7,3],[3,8,6,5]] 12 | let solution = checksum(part2TestSpreadsheet,findDivisors) 13 | expect(solution).toEqual(9) 14 | }) 15 | }); -------------------------------------------------------------------------------- /spec/2017-04-Spec.js: -------------------------------------------------------------------------------- 1 | let { isValid1,isValid2 } = require("../2017/04/solve") 2 | 3 | describe("2017 day 4", function() { 4 | it ("aa bb cc dd ee is valid part 1 passphrase", function() { 5 | const valid = isValid1("aa bb cc dd ee"); 6 | expect(valid).toBe(true); 7 | }) 8 | 9 | it ("aa bb cc dd aa is invalid part 1 passphrase", function() { 10 | const valid = isValid1("aa bb cc dd aa"); 11 | expect(valid).toBe(false); 12 | }) 13 | 14 | it ("aa bb cc dd aaa is valid part 1 passphrase", function() { 15 | const valid = isValid1("aa bb cc dd aaa"); 16 | expect(valid).toBe(true); 17 | }); 18 | 19 | it ("abcde fghij is valid part 2 passphrase", function() { 20 | const valid = isValid2("abcde fghij"); 21 | expect(valid).toBe(true); 22 | }); 23 | 24 | it ("abcde xyz ecdab is invalid part 2 passphrase", function() { 25 | const valid = isValid2("abcde xyz ecdab"); 26 | expect(valid).toBe(false); 27 | }); 28 | 29 | it ("a ab abc abd abf abj is valid part 2 passphrase", function() { 30 | const valid = isValid2("a ab abc abd abf abj"); 31 | expect(valid).toBe(true); 32 | }); 33 | 34 | it ("iiii oiii ooii oooi oooo is valid part 2 passphrase", function() { 35 | const valid = isValid2("iiii oiii ooii oooi oooo"); 36 | expect(valid).toBe(true); 37 | }); 38 | 39 | it ("oiii ioii iioi iiio is invalid part 2 passphrase", function() { 40 | const valid = isValid2("oiii ioii iioi iiio"); 41 | expect(valid).toBe(false); 42 | }); 43 | 44 | }); -------------------------------------------------------------------------------- /spec/2017-05-Spec.js: -------------------------------------------------------------------------------- 1 | let { countStepsUntilExit } = require("../2017/05/solve") 2 | 3 | describe("2017 day 5", function() { 4 | it ("passes the part 1 test cast", function() { 5 | const steps = countStepsUntilExit([0,3,0,1,-3], () => 1) 6 | expect(steps).toBe(5); 7 | }) 8 | 9 | it ("passes the part 2 test cast", function() { 10 | const steps = countStepsUntilExit([0,3,0,1,-3], n => (n>=3)?-1:1) 11 | expect(steps).toBe(10); 12 | }) 13 | }); -------------------------------------------------------------------------------- /spec/2017-06-Spec.js: -------------------------------------------------------------------------------- 1 | const { redistribute,countRedistributions } = require("../2017/06/solve") 2 | 3 | describe("2017 day 6", function() { 4 | it ("solves the part 1 test case", function() { 5 | const count = countRedistributions([0,2,7,0]).redistributions 6 | expect(count).toBe(5); 7 | }) 8 | 9 | it ("passes the part 2 test case", function() { 10 | const count = countRedistributions([0,2,7,0]).loopSize 11 | expect(count).toBe(4); 12 | }) 13 | 14 | 15 | it ("correctly redistributes", function() { 16 | let banks = redistribute([0,2,7,0]) 17 | expect(banks).toEqual([2,4,1,2]); 18 | banks = redistribute(banks) 19 | expect(banks).toEqual([3,1,2,3]); 20 | banks = redistribute(banks) 21 | expect(banks).toEqual([0,2,3,4]); 22 | banks = redistribute(banks) 23 | expect(banks).toEqual([1,3,4,1]); 24 | banks = redistribute(banks) 25 | expect(banks).toEqual([2,4,1,2]); 26 | }) 27 | }); -------------------------------------------------------------------------------- /spec/2017-07-Spec.js: -------------------------------------------------------------------------------- 1 | const { part1,part2,findDifferentIndex } = require("../2017/07/solve") 2 | 3 | const testInput = [ "pbga (66)", 4 | "xhth (57)", 5 | "ebii (61)", 6 | "havc (66)", 7 | "ktlj (57)", 8 | "fwft (72) -> ktlj, cntj, xhth", 9 | "qoyq (66)", 10 | "padx (45) -> pbga, havc, qoyq", 11 | "tknk (41) -> ugml, padx, fwft", 12 | "jptl (61)", 13 | "ugml (68) -> gyxo, ebii, jptl", 14 | "gyxo (61)", 15 | "cntj (57)`;" ] 16 | 17 | describe("2017 day 7", function() { 18 | it ("solves the part 1 test case", function() { 19 | expect(part1(testInput)).toBe("tknk"); 20 | }) 21 | 22 | it ("solves the part 2 test case", function() { 23 | expect(part2(testInput)).toBe(60); 24 | }) 25 | 26 | it ("finds different index if different is first", function() { 27 | expect(findDifferentIndex([2,1,1,1])).toEqual([0,1]) 28 | }) 29 | 30 | it ("finds different index if different is last", function() { 31 | expect(findDifferentIndex([1,1,1,2])).toEqual([3,0]) 32 | }) 33 | 34 | it ("finds different index if different is second", function() { 35 | expect(findDifferentIndex([1,2,1,1])).toEqual([1,0]) 36 | }) 37 | 38 | it ("handles two input arrays", function() { 39 | // arbitrary decision here - [0,1] or [1,0] equally valid outputs 40 | expect(findDifferentIndex([1,2])).toEqual([0,1]) 41 | }) 42 | }); -------------------------------------------------------------------------------- /spec/2017-09-Spec.js: -------------------------------------------------------------------------------- 1 | const { parseInput } = require("../2017/09/solve") 2 | 3 | const testScores = [ ['{}', 1 ], 4 | [ '{{{}}}', 6 ], 5 | [ '{{},{}}', 5 ], 6 | [ '{{{},{},{{}}}}', 16 ], 7 | [ '{,,,}', 1 ], 8 | [ '{{},{},{},{}}', 9 ], 9 | [ '{{},{},{},{}}', 9 ], 10 | [ '{{},{},{},{}}', 3 ] ] 11 | 12 | const garbageCounts = [ 13 | [ '<>', 0 ], 14 | [ '', 17 ], 15 | [ '<<<<>', 3 ], 16 | [ '<{!>}>', 2 ], 17 | [ '', 0 ], 18 | [ '>', 0 ], 19 | [ '<{o"i!a,<{i', 10 ], 20 | ]; 21 | 22 | describe("2017 day 9", function() { 23 | it ("scores the tests correctly", function() { 24 | for (let [s,n] of testScores) 25 | expect(parseInput(s)[0]).toBe(n); 26 | }) 27 | 28 | it ("counts garbage chars correctly", function() { 29 | for (let [s,n] of garbageCounts) 30 | expect(parseInput(s)[1]).toBe(n); 31 | }) 32 | }); -------------------------------------------------------------------------------- /spec/2017-10-Spec.js: -------------------------------------------------------------------------------- 1 | const { reverseSection,applyLengths,hashString,toHex } = require("../2017/10/solve") 2 | 3 | const reverseTests = [ [[0,1,2,3,4], 0, 2, [1,0,2,3,4] ], 4 | [[0,1,2,3,4], 1, 3, [0,3,2,1,4] ], 5 | [[0,1,2,3,4], 2, 3, [0,1,4,3,2] ], 6 | [[0,1,2,3,4], 3, 3, [3,1,2,0,4] ], 7 | ] 8 | 9 | const hashTests = [ 10 | ["", "a2582a3a0e66e6e86e3812dcb672a272"], 11 | ["AoC 2017" , "33efeb34ea91902bb2f59c9920caa6cd"], 12 | ["1,2,3", "3efbe78a8d82f29979031a4aa0b16a9d"], 13 | ["1,2,4", "63960835bcdc130f0b66d7ff4f6a5a8e"] 14 | ] 15 | 16 | describe("2017 day 10", function() { 17 | it ("can reverse sections", function() { 18 | for (let [input,pos,len,expected] of reverseTests) 19 | expect(reverseSection(input,pos,len)).toEqual(expected); 20 | }) 21 | 22 | it ("can apply lengths", function() { 23 | let {result} = applyLengths([0,1,2,3,4],[3, 4, 1, 5]); 24 | expect(result).toEqual([3,4,2,1,0]); 25 | }) 26 | 27 | it ("can hash strings", function() { 28 | for (let [input,expected] of hashTests) 29 | expect(toHex(hashString(input))).toEqual(expected); 30 | }) 31 | }); -------------------------------------------------------------------------------- /spec/2017-15-Spec.js: -------------------------------------------------------------------------------- 1 | const { generator } = require("../2017/15/solve") 2 | const { take } = require("../utils/utils") 3 | const aFactor = 16807, bFactor = 48271 4 | 5 | describe("2017 day 15", function() { 6 | it ("can produce generator A test output", function() { 7 | let actual = [...take(generator(65,aFactor),5)] 8 | expect(actual).toEqual([1092455,1181022009,245556042,1744312007,1352636452]); 9 | }) 10 | 11 | it ("can produce generator A test output", function() { 12 | let actual = [...take(generator(8921,bFactor),5)] 13 | expect(actual).toEqual([430625591,1233683848,1431495498,137874439,285222916]); 14 | }) 15 | }); -------------------------------------------------------------------------------- /spec/support/jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "spec_dir": "spec", 3 | "spec_files": [ 4 | "**/*[sS]pec.js" 5 | ], 6 | "helpers": [ 7 | "helpers/**/*.js" 8 | ], 9 | "stopSpecOnExpectationFailure": false, 10 | "random": false 11 | } 12 | -------------------------------------------------------------------------------- /spec/utils/countSpec.js: -------------------------------------------------------------------------------- 1 | let { count,range } = require("../../utils/utils") 2 | describe("count util", function() { 3 | it ("can count an empty array", function() { 4 | let solution = count([]); 5 | expect(solution).toBe(0) 6 | }) 7 | 8 | it ("can count a one element array", function() { 9 | let solution = count([1]); 10 | expect(solution).toBe(1) 11 | }) 12 | 13 | it ("can count a three element array", function() { 14 | let solution = count([1,4,6]); 15 | expect(solution).toBe(3) 16 | }) 17 | 18 | it ("can count any iterable", function() { 19 | let solution = count(new Map([[1,2],[3,4]])); 20 | expect(solution).toBe(2) 21 | }) 22 | 23 | it ("can apply predicate", function() { 24 | let solution = count(range(1,6),n => n%2 === 1); 25 | expect(solution).toBe(3) 26 | }) 27 | 28 | }) -------------------------------------------------------------------------------- /spec/utils/firstRepeatedValueSpec.js: -------------------------------------------------------------------------------- 1 | let { firstRepeatedValue,firstRepeatedElement } = require("../../utils/utils") 2 | describe("firstRepeatedValue util", function() { 3 | it ("finds an immediate repeat", function() { 4 | let actual = firstRepeatedValue([1,1,1,1], 3) 5 | expect(actual).toEqual(1) 6 | }) 7 | it ("finds a repeat", function() { 8 | let actual = firstRepeatedValue([2,3,4,1,1,1,2,4], 3) 9 | expect(actual).toEqual(1) 10 | }) 11 | it ("finds a repeat at the end", function() { 12 | let actual = firstRepeatedValue([2,3,4,2,4,1,1,1], 3) 13 | expect(actual).toEqual(1) 14 | }) 15 | it ("resumes after partial repeat", function() { 16 | let actual = firstRepeatedValue([2,3,4,1,1,2,4,5,1,1,1], 3) 17 | expect(actual).toEqual(1) 18 | }) 19 | it ("can find with selector", function() { 20 | let actual = firstRepeatedValue(["bear","apple","pear","dog","cat","ant","tiger"], 3, s => s.length) 21 | expect(actual).toEqual(3) 22 | }) 23 | it ("can find element with selector", function() { 24 | let actual = firstRepeatedElement(["bear","apple","pear","dog","cat","ant","tiger"], 3, s => s.length) 25 | expect(actual).toEqual("dog") 26 | }) 27 | }) -------------------------------------------------------------------------------- /spec/utils/flatMapSpec.js: -------------------------------------------------------------------------------- 1 | let { flatMap } = require("../../utils/utils") 2 | describe("flatMap util", function() { 3 | it ("flatMap array of arrays", function() { 4 | let solution = [...flatMap([[1],[2,2],[3,3,3]],f => f)]; 5 | expect(solution).toEqual([1,2,2,3,3,3]) 6 | }) 7 | 8 | it ("flatMap strings", function() { 9 | let solution = [...flatMap(["apple","banana","cat"],f => [f[0],f.length])]; 10 | expect(solution).toEqual(['a',5,'b',6,'c',3]) 11 | }) 12 | 13 | it ("flatMap selector is optional", function() { 14 | let solution = [...flatMap([[1],[2,2],[3,3,3]])]; 15 | expect(solution).toEqual([1,2,2,3,3,3]) 16 | }) 17 | }) -------------------------------------------------------------------------------- /spec/utils/nonRepeatedSpec.js: -------------------------------------------------------------------------------- 1 | let { nonRepeated } = require("../../utils/utils") 2 | describe("nonRepeated util", function() { 3 | it ("filters a single repeat", function() { 4 | let actual = [...nonRepeated([1,1,2,3])] 5 | expect(actual).toEqual([2,3]) 6 | }) 7 | it ("filters a double repeat", function() { 8 | let actual = [...nonRepeated([1,1,2,3,1])] 9 | expect(actual).toEqual([2,3]) 10 | }) 11 | it ("supports selector", function() { 12 | let actual = [...nonRepeated(["cat","dog","horse","cow","bear"], s => s.length)] 13 | expect(actual).toEqual(["horse","bear"]) 14 | }) 15 | }) -------------------------------------------------------------------------------- /spec/utils/reduceSpec.js: -------------------------------------------------------------------------------- 1 | let { reduce } = require("../../utils/utils") 2 | describe("reduce util", function() { 3 | it ("can sum numbers", function() { 4 | let solution = reduce([1,2,3],(a,b) => a+b,0); 5 | expect(solution).toBe(6) 6 | }) 7 | 8 | it ("can concatenate strings", function() { 9 | let solution = reduce(['a','b','c'],(a,b) => a+(a === ""?"":",")+b,""); 10 | expect(solution).toBe("a,b,c") 11 | }) 12 | }) -------------------------------------------------------------------------------- /spec/utils/skipSpec.js: -------------------------------------------------------------------------------- 1 | let { skip } = require("../../utils/utils") 2 | describe("skip util", function() { 3 | it ("can skip 3 elements", function() { 4 | let actual = [...skip([1,2,3,4,5],3)] 5 | expect(actual).toEqual([4,5]) 6 | }) 7 | it ("can skip entire sequence", function() { 8 | let actual = [...skip([1,2,3,4,5],8)] 9 | expect(actual).toEqual([]) 10 | }) 11 | it ("can skip nothing", function() { 12 | let actual = [...skip([1,2,3,4,5],0)] 13 | expect(actual).toEqual([1,2,3,4,5]) 14 | }) 15 | 16 | }) -------------------------------------------------------------------------------- /spec/utils/unfoldSpec.js: -------------------------------------------------------------------------------- 1 | let { unfold,take } = require("../../utils/utils") 2 | describe("unfold util", function() { 3 | it ("can produce double", function() { 4 | let actual = [...take(unfold(1,x => x * 2),5)] 5 | expect(actual).toEqual([1,2,4,8,16]) 6 | }) 7 | 8 | }) -------------------------------------------------------------------------------- /spec/utils/zipSpec.js: -------------------------------------------------------------------------------- 1 | let { zip,range } = require("../../utils/utils") 2 | describe("zip util", function() { 3 | it ("can zip sequences of equal length", function() { 4 | let actual = [...zip(range(4,5),range(10,5))] 5 | expect(actual).toEqual([[4,10],[5,11],[6,12],[7,13],[8,14]]) 6 | }) 7 | it ("can zip sequences first is longer", function() { 8 | let actual = [...zip(range(4,8),range(10,5))] 9 | expect(actual).toEqual([[4,10],[5,11],[6,12],[7,13],[8,14]]) 10 | }) 11 | it ("can zip sequences second is longer", function() { 12 | let actual = [...zip(range(4,5),range(10,8))] 13 | expect(actual).toEqual([[4,10],[5,11],[6,12],[7,13],[8,14]]) 14 | }) 15 | 16 | }) -------------------------------------------------------------------------------- /spec/utilsSpec.js: -------------------------------------------------------------------------------- 1 | let { bfs,scan } = require("../utils/utils") 2 | describe("Utils", function() { 3 | it ("can do a basic breadth first search", function() { 4 | let solution = bfs(s => s === "abba", s => [ s+"b", s+"a" ] , "a").next().value; 5 | expect(solution).toEqual("abba") 6 | }) 7 | 8 | it ("can keep a running total", function() { 9 | let solution = [...scan([2,2,2,2],(a,b) => a+b, 0)]; 10 | expect(solution).toEqual([0,2,4,6,8]) 11 | }) 12 | it ("can keep a running total without start state", function() { 13 | let solution = [...scan([2,2,2,2],(a,b) => a+b)]; 14 | expect(solution).toEqual([2,4,6,8]) 15 | }) 16 | }) -------------------------------------------------------------------------------- /utils/utils.js: -------------------------------------------------------------------------------- 1 | function* scan(source, folder, startState) { 2 | let state = startState; 3 | if (typeof(state) !== "undefined" ) { 4 | yield startState; 5 | } 6 | for (let n of source) { 7 | if (typeof(state) === "undefined" ) { 8 | state = n; 9 | } 10 | else { 11 | state = folder(state, n); 12 | } 13 | yield state; 14 | } 15 | } 16 | 17 | //https://stackoverflow.com/a/20871714/7532 18 | function permutations(inputArr) { 19 | let results = []; 20 | 21 | function permute(arr, memo) { 22 | let cur; 23 | memo = memo || []; 24 | 25 | for (var i = 0; i < arr.length; i++) { 26 | cur = arr.splice(i, 1); 27 | if (arr.length === 0) { 28 | results.push(memo.concat(cur)); 29 | } 30 | permute(arr.slice(), memo.concat(cur)); 31 | arr.splice(i, 0, cur[0]); 32 | } 33 | 34 | return results; 35 | } 36 | return permute(inputArr); 37 | } 38 | 39 | function* flatMap(xs,f) { 40 | for (let x of xs) { 41 | if (f) yield *f(x); else yield *x; 42 | } 43 | } 44 | 45 | function pairwise(arr) { 46 | let out = []; 47 | for (let n = 1; n < arr.length; n++) { 48 | out.push([arr[n-1],arr[n]]); 49 | } 50 | return out; 51 | } 52 | 53 | function* range(start, count) { 54 | for (let n = 0; typeof(count) === 'undefined' || n < count; n++) { 55 | yield start++; 56 | } 57 | } 58 | 59 | function* batch(seq, size) { 60 | let b = [] 61 | for(let el of seq) { 62 | b.push(el) 63 | if (b.length === size) { 64 | yield b; 65 | b = [] 66 | } 67 | } 68 | if (b.length > 0) 69 | yield b 70 | } 71 | 72 | function sumBy(seq, selector) { 73 | let total = 0; 74 | for(let n of seq) { 75 | total += (typeof(selector) === 'undefined') ? n : selector(n); 76 | } 77 | return total; 78 | } 79 | 80 | const sum = sumBy; // alias 81 | 82 | function findBy(seq, selector, test) { 83 | let foundVal; 84 | let foundElem; 85 | for(let n of seq) { 86 | let val = (typeof(selector) === 'undefined') ? n : selector(n); 87 | if (typeof(foundElem) === 'undefined' || test(val,foundVal)) { 88 | foundElem = n; 89 | foundVal = val; 90 | } 91 | } 92 | return { foundVal, foundElem }; 93 | } 94 | 95 | function maxBy(seq, selector) { 96 | return findBy(seq,selector,(a,b) => a > b).foundElem; 97 | } 98 | 99 | function minBy(seq, selector) { 100 | return findBy(seq,selector,(a,b) => a < b).foundElem; 101 | } 102 | 103 | function max(seq, selector) { 104 | return findBy(seq,selector,(a,b) => a > b).foundVal; 105 | } 106 | 107 | function min(seq, selector) { 108 | return findBy(seq,selector,(a,b) => a < b).foundVal; 109 | } 110 | 111 | function shuffle(array) { 112 | for (let i = array.length - 1; i > 0; i--) { 113 | let j = Math.floor(Math.random() * (i + 1)); 114 | [array[i], array[j]] = [array[j], array[i]]; 115 | } 116 | } 117 | 118 | function bfs(isSolution, getChildren, start) { 119 | let q = [start] 120 | function *search() { 121 | if (q.length > 0) { 122 | let s = q.shift() 123 | if (isSolution(s)) { 124 | yield s; 125 | } 126 | q.push(...getChildren(s)) 127 | yield* search() 128 | } 129 | } 130 | return search(); 131 | } 132 | 133 | // way to get all matches for a regex 134 | function* matches(str, regex) { 135 | let match; 136 | while((match = regex.exec(str)) !== null) { 137 | yield match; 138 | } 139 | return matches; 140 | } 141 | 142 | function any(seq, predicate) { 143 | if (typeof(predicate) === 'undefined') 144 | return !seq[Symbol.iterator]().next().done 145 | for(let el of seq) { 146 | if (predicate(el)) return true; 147 | } 148 | return false; 149 | } 150 | 151 | function first(seq, predicate) { 152 | if (typeof(predicate) === 'undefined') 153 | return seq[Symbol.iterator]().next().value 154 | for(let el of seq) { 155 | if (predicate(el)) return el; 156 | } 157 | } 158 | 159 | function* where(seq, filter) { 160 | for (let el of seq) { 161 | if (filter(el)) yield el; 162 | } 163 | } 164 | 165 | function* map(seq, fn) { 166 | for (let el of seq) { 167 | yield fn(el); 168 | } 169 | } 170 | 171 | function reduce(seq, fn, acc) { 172 | for (let el of seq) { 173 | acc = fn(acc,el); 174 | } 175 | return acc; 176 | } 177 | 178 | function count(seq, predicate) { 179 | let n = 0; 180 | for(let el of seq) { 181 | if (!predicate || predicate(el)) n++ 182 | } 183 | return n; 184 | } 185 | 186 | function *take(seq, count) { 187 | let n = 0; 188 | for(let el of seq) { 189 | if (++n > count) return; 190 | yield el; 191 | } 192 | } 193 | 194 | function *skip(seq, count) { 195 | let n = 0; 196 | for(let el of seq) { 197 | if (++n > count) yield el; 198 | } 199 | } 200 | 201 | function *zip(seq1,seq2) { 202 | let it1 = seq1[Symbol.iterator]() 203 | let it2 = seq2[Symbol.iterator]() 204 | for(;;) { 205 | let el1 = it1.next() 206 | if(el1.done) return; 207 | let el2 = it2.next() 208 | if(el2.done) return; 209 | yield [el1.value,el2.value] 210 | } 211 | } 212 | 213 | function firstRepeated(seq, repeats, selector) { 214 | let current; 215 | let currentEl; 216 | let count = 0; 217 | for(let el of seq) { 218 | let testVal = (selector ? selector(el) : el) 219 | if (testVal === current) { 220 | count++; 221 | if (count >= repeats) return [current,currentEl] 222 | } 223 | else { 224 | current = testVal 225 | currentEl = el 226 | count = 1; 227 | } 228 | } 229 | throw new Error("Repeated element not found") 230 | } 231 | 232 | function firstRepeatedValue(seq, repeats, selector) { 233 | return firstRepeated(seq, repeats, selector)[0] 234 | } 235 | 236 | function firstRepeatedElement(seq, repeats, selector) { 237 | return firstRepeated(seq, repeats, selector)[1] 238 | } 239 | 240 | 241 | function nonRepeated(seq, selector) { 242 | let map = new Map() 243 | for (let el of seq) { 244 | let key = selector ? selector(el) : el; 245 | if (!map.has(key)) { 246 | map.set(key, el) 247 | } 248 | else { 249 | map.set(key, undefined) // don't delete to eliminate three at same pos 250 | } 251 | } 252 | return where(map.values(),n => n !== undefined) 253 | } 254 | 255 | function* unfold(start, fn) { 256 | yield start; 257 | for(;;) { 258 | start = fn(start) 259 | yield start 260 | } 261 | } 262 | 263 | module.exports = { 264 | scan,pairwise,permutations,flatMap, 265 | range,sumBy,maxBy,minBy,bfs, 266 | min,max,shuffle,matches,take,zip,skip, 267 | batch,sum,any,first,where,map,count,reduce, 268 | firstRepeatedValue,nonRepeated,unfold,firstRepeatedElement 269 | } --------------------------------------------------------------------------------