From 2283146f8365bb052988027435ddd68f553bbe34 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 1 Dec 2022 18:40:32 +0100 Subject: [PATCH 001/120] Remove 2020 and 2021. These are still available in the history and on the branch `2021`, for 2022 I'll try a bit a different organization and also switch to golang for some learning. --- .editorconfig | 5 - .gitignore | 2 - .prettierrc.json | 20 - .vscode/extensions.json | 2 +- .vscode/launch.json | 23 - .vscode/settings.json | 5 +- .vscode/tasks.json | 34 - 2020/day-1.input | 200 --- 2020/day-1.ts | 75 -- 2020/day-10-example-1.input | 11 - 2020/day-10-example-2.input | 31 - 2020/day-10.input | 103 -- 2020/day-10.ts | 97 -- 2020/day-11-example.input | 10 - 2020/day-11.input | 97 -- 2020/day-11.ts | 116 -- 2020/day-12-example.input | 5 - 2020/day-12.input | 776 ------------ 2020/day-12.ts | 121 -- 2020/day-14-example-2.input | 4 - 2020/day-14-example.input | 4 - 2020/day-14.input | 554 --------- 2020/day-14.ts | 207 ---- 2020/day-15.ts | 63 - 2020/day-16-example.input | 12 - 2020/day-16.input | 269 ---- 2020/day-16.ts | 141 --- 2020/day-2.input | 1000 --------------- 2020/day-2.ts | 47 - 2020/day-3.input | 323 ----- 2020/day-3.ts | 31 - 2020/day-4.input | 1031 ---------------- 2020/day-4.ts | 71 -- 2020/day-5.input | 901 -------------- 2020/day-5.ts | 23 - 2020/day-6-example.input | 15 - 2020/day-6.input | 2087 -------------------------------- 2020/day-6.ts | 38 - 2020/day-7-example-2.input | 7 - 2020/day-7-example.input | 9 - 2020/day-7.input | 594 --------- 2020/day-7.ts | 100 -- 2020/day-8-example.input | 9 - 2020/day-8.input | 613 ---------- 2020/day-8.ts | 86 -- 2020/day-9-example.input | 20 - 2020/day-9.input | 1000 --------------- 2020/day-9.ts | 79 -- 2021/day-1-example.input | 10 - 2021/day-1.input | 2000 ------------------------------ 2021/day-1.ts | 41 - 2021/day-10-example.input | 10 - 2021/day-10.input | 110 -- 2021/day-10.ts | 141 --- 2021/day-11-example-mini.input | 5 - 2021/day-11-example.input | 10 - 2021/day-11-example.output | 239 ---- 2021/day-11.input | 10 - 2021/day-11.ts | 151 --- 2021/day-12-example-1.input | 7 - 2021/day-12-example-2.input | 10 - 2021/day-12-example-3.input | 18 - 2021/day-12.input | 23 - 2021/day-12.ts | 150 --- 2021/day-13-example.input | 21 - 2021/day-13.input | 934 -------------- 2021/day-13.ts | 165 --- 2021/day-14-example.input | 18 - 2021/day-14.input | 102 -- 2021/day-14.ts | 124 -- 2021/day-2-example.input | 6 - 2021/day-2.input | 1000 --------------- 2021/day-2.ts | 53 - 2021/day-3-example.input | 12 - 2021/day-3.input | 1000 --------------- 2021/day-3.ts | 162 --- 2021/day-4-example.input | 19 - 2021/day-4.input | 601 --------- 2021/day-4.ts | 175 --- 2021/day-5-example.input | 10 - 2021/day-5.input | 500 -------- 2021/day-5.ts | 136 --- 2021/day-6-example.input | 1 - 2021/day-6.input | 1 - 2021/day-6.ts | 99 -- 2021/day-7-example.input | 1 - 2021/day-7.input | 1 - 2021/day-7.ts | 91 -- 2021/day-8-example.input | 10 - 2021/day-8.input | 200 --- 2021/day-8.ts | 195 --- 2021/day-9-example.input | 5 - 2021/day-9.input | 100 -- 2021/day-9.ts | 212 ---- package-lock.json | 54 - package.json | 21 - skeleton.ts | 42 - tsconfig.json | 9 - utils.ts | 19 - 99 files changed, 5 insertions(+), 20100 deletions(-) delete mode 100644 .prettierrc.json delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/tasks.json delete mode 100644 2020/day-1.input delete mode 100644 2020/day-1.ts delete mode 100644 2020/day-10-example-1.input delete mode 100644 2020/day-10-example-2.input delete mode 100644 2020/day-10.input delete mode 100644 2020/day-10.ts delete mode 100644 2020/day-11-example.input delete mode 100644 2020/day-11.input delete mode 100644 2020/day-11.ts delete mode 100644 2020/day-12-example.input delete mode 100644 2020/day-12.input delete mode 100644 2020/day-12.ts delete mode 100644 2020/day-14-example-2.input delete mode 100644 2020/day-14-example.input delete mode 100644 2020/day-14.input delete mode 100644 2020/day-14.ts delete mode 100644 2020/day-15.ts delete mode 100644 2020/day-16-example.input delete mode 100644 2020/day-16.input delete mode 100644 2020/day-16.ts delete mode 100644 2020/day-2.input delete mode 100644 2020/day-2.ts delete mode 100644 2020/day-3.input delete mode 100644 2020/day-3.ts delete mode 100644 2020/day-4.input delete mode 100644 2020/day-4.ts delete mode 100644 2020/day-5.input delete mode 100644 2020/day-5.ts delete mode 100644 2020/day-6-example.input delete mode 100644 2020/day-6.input delete mode 100644 2020/day-6.ts delete mode 100644 2020/day-7-example-2.input delete mode 100644 2020/day-7-example.input delete mode 100644 2020/day-7.input delete mode 100644 2020/day-7.ts delete mode 100644 2020/day-8-example.input delete mode 100644 2020/day-8.input delete mode 100644 2020/day-8.ts delete mode 100644 2020/day-9-example.input delete mode 100644 2020/day-9.input delete mode 100644 2020/day-9.ts delete mode 100644 2021/day-1-example.input delete mode 100644 2021/day-1.input delete mode 100644 2021/day-1.ts delete mode 100644 2021/day-10-example.input delete mode 100644 2021/day-10.input delete mode 100644 2021/day-10.ts delete mode 100644 2021/day-11-example-mini.input delete mode 100644 2021/day-11-example.input delete mode 100644 2021/day-11-example.output delete mode 100644 2021/day-11.input delete mode 100644 2021/day-11.ts delete mode 100644 2021/day-12-example-1.input delete mode 100644 2021/day-12-example-2.input delete mode 100644 2021/day-12-example-3.input delete mode 100644 2021/day-12.input delete mode 100644 2021/day-12.ts delete mode 100644 2021/day-13-example.input delete mode 100644 2021/day-13.input delete mode 100644 2021/day-13.ts delete mode 100644 2021/day-14-example.input delete mode 100644 2021/day-14.input delete mode 100644 2021/day-14.ts delete mode 100644 2021/day-2-example.input delete mode 100644 2021/day-2.input delete mode 100644 2021/day-2.ts delete mode 100644 2021/day-3-example.input delete mode 100644 2021/day-3.input delete mode 100644 2021/day-3.ts delete mode 100644 2021/day-4-example.input delete mode 100644 2021/day-4.input delete mode 100644 2021/day-4.ts delete mode 100644 2021/day-5-example.input delete mode 100644 2021/day-5.input delete mode 100644 2021/day-5.ts delete mode 100644 2021/day-6-example.input delete mode 100644 2021/day-6.input delete mode 100644 2021/day-6.ts delete mode 100644 2021/day-7-example.input delete mode 100644 2021/day-7.input delete mode 100644 2021/day-7.ts delete mode 100644 2021/day-8-example.input delete mode 100644 2021/day-8.input delete mode 100644 2021/day-8.ts delete mode 100644 2021/day-9-example.input delete mode 100644 2021/day-9.input delete mode 100644 2021/day-9.ts delete mode 100644 package-lock.json delete mode 100644 package.json delete mode 100644 skeleton.ts delete mode 100644 tsconfig.json delete mode 100644 utils.ts diff --git a/.editorconfig b/.editorconfig index 2135811..0385e34 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,8 +7,3 @@ root = true [*] end_of_line = lf insert_final_newline = true - -[*.ts] -charset = utf-8 -indent_style = tab -indent_size = 4 diff --git a/.gitignore b/.gitignore index 97c55b2..89f9ac0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ -node_modules/ out/ -*.tsbuildinfo diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 611b3cc..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "arrowParens": "always", - "bracketSpacing": true, - "endOfLine": "lf", - "htmlWhitespaceSensitivity": "css", - "insertPragma": false, - "jsxBracketSameLine": false, - "jsxSingleQuote": false, - "printWidth": 80, - "proseWrap": "preserve", - "quoteProps": "as-needed", - "requirePragma": false, - "semi": true, - "singleQuote": true, - "tabWidth": 4, - "trailingComma": "es5", - "useTabs": true, - "vueIndentScriptAndStyle": false, - "parser": "typescript" -} \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 545de88..db58406 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,5 @@ { "recommendations": [ - "esbenp.prettier-vscode" + "golang.Go" ] } diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 9f1191d..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "pwa-node", - "request": "launch", - "name": "launch", - "skipFiles": [ - "/**" - ], - "program": "${workspaceFolder}/2021/day-16.ts", - "preLaunchTask": "npm: build", - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "console": "integratedTerminal", - "cwd": "${workspaceFolder}/2021" - }, - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json index 8beecf9..2ee1498 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,8 @@ { "editor.formatOnSave": true, "editor.formatOnSaveMode": "modificationsIfAvailable", - "editor.defaultFormatter": "esbenp.prettier-vscode" + "[go]": { + "editor.insertSpaces": true, + "editor.defaultFormatter": "golang.go" + }, } diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index ef39c26..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "build", - "problemMatcher": [ - "$tsc" - ], - "group": "build", - "label": "npm: build", - "detail": "tsc -p tsconfig.json", - "presentation": { - "echo": false, - "reveal": "silent", - "focus": false, - "panel": "shared", - } - }, - { - "type": "npm", - "script": "watch", - "group": "build", - "problemMatcher": [ - "$tsc-watch" - ], - "label": "npm: watch", - "detail": "tsc -p tsconfig.json -w", - "isBackground": true - } - ] -} \ No newline at end of file diff --git a/2020/day-1.input b/2020/day-1.input deleted file mode 100644 index 7ec26db..0000000 --- a/2020/day-1.input +++ /dev/null @@ -1,200 +0,0 @@ -1826 -1895 -1427 -1931 -1651 -1638 -1507 -1999 -1886 -1824 -1902 -1995 -1945 -1735 -1823 -1595 -1936 -1476 -2010 -1833 -1932 -1772 -1791 -1814 -1783 -1957 -1901 -1600 -1502 -1521 -1812 -1974 -1880 -1790 -1672 -1541 -1807 -426 -1858 -1699 -1964 -1996 -1983 -1498 -1863 -1976 -1492 -1930 -1838 -1941 -1764 -1929 -1897 -2009 -1853 -1753 -1759 -1860 -1952 -1988 -1727 -1751 -1943 -1830 -1645 -1907 -1857 -1714 -1798 -1944 -1868 -1630 -959 -2003 -1987 -1890 -1962 -1928 -1872 -1912 -1709 -1809 -1650 -1980 -1737 -1898 -1817 -1736 -1991 -1788 -1776 -1845 -1854 -1963 -1554 -1949 -1576 -1819 -1960 -699 -1990 -1757 -1698 -1596 -304 -1982 -1477 -1961 -1636 -1619 -1946 -1876 -1592 -1848 -1707 -1958 -1874 -1867 -52 -1881 -1665 -1463 -1799 -1979 -677 -1710 -1869 -1639 -1787 -1633 -1956 -1457 -1581 -2005 -1782 -1904 -1910 -62 -1593 -1695 -1915 -1922 -1797 -1715 -1981 -1925 -1893 -1562 -1789 -2008 -1939 -1669 -1992 -1652 -117 -1609 -1686 -1953 -2007 -599 -1547 -1959 -1691 -1520 -1444 -1641 -887 -1579 -1778 -1977 -1768 -1942 -1713 -1603 -1926 -1855 -1655 -1673 -1887 -1994 -1839 -1725 -928 -1771 -1761 -1971 -1571 -1806 -1821 -1624 -1701 -1436 -1748 -1921 -1617 -2004 -1792 -1732 -1740 -1831 \ No newline at end of file diff --git a/2020/day-1.ts b/2020/day-1.ts deleted file mode 100644 index ac15c44..0000000 --- a/2020/day-1.ts +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env node - -import { createInterface } from 'readline'; -import { createReadStream } from 'fs'; - -import { qs } from '../utils'; - -function part1BruteForce(numbers: number[]): [number, number, number] { - for (let i = 0; i < numbers.length; i++) { - for (let j = 0; j < numbers.length; j++) { - if (i === j) { - continue - } else if (numbers[i] + numbers[j] === 2020) { - const product = numbers[i] * numbers[j]; - console.log(`Brute force: ${numbers[i]} + ${numbers[j]} = 2020; product: ${product}`); - return [numbers[i], numbers[j], product]; - } - } - } - throw new Error('Not found!'); -} - -function part1IndexOf(numbers: number[], sum: number = 2020, indexBlacklist: number[] = []): [number, number, number] { - for (let i = 0; i < numbers.length; i++) { - if (indexBlacklist.includes(i)) { - continue; - } - const number = numbers[i]; - const needed = sum - number; - const neededIndex = qs(numbers, needed); - if (neededIndex >= 0 && neededIndex !== i) { - const product = needed * number; - console.log(`indexOf: ${number} + ${needed} = ${sum}; product: ${product}`); - return [number, needed, product]; - } - } - throw new Error('Not found'); -} - -function part2IndexOf(numbers: number[]): [number, number, number, number] { - for (let i = 0; i < numbers.length; i++) { - const number = numbers[i]; - const needed = 2020 - number; - try { - const [number2, number3, partProduct] = part1IndexOf(numbers, needed, [i]); - const product = number * partProduct; - console.log(`part 2: indexOf: ${number} + ${number2} + ${number3} = 2020; product: ${product}`); - return [number, number2, number, product]; - } catch (err) { - // Ignored - } - } - throw new Error('Not found'); -} - -const numbers: number[] = []; - -// Self-test -console.log(qs([0,1,2,3], 0)); -console.log(qs([0,1,2,3], 1)); -console.log(qs([0,1,2,3], 2)); -console.log(qs([0,1,2,3], 3)); -console.log(qs([0,1,2,3], 5)); - -const rl = createInterface(createReadStream('day-1.input')); -rl.on('line', line => { - numbers.push(Number(line)); -}); -rl.on('close', () => { - console.log(`Have ${numbers.length} numbers`); - const sorted = numbers.sort(); - part1BruteForce(sorted); - part1IndexOf(sorted); - part2IndexOf(sorted); -}); \ No newline at end of file diff --git a/2020/day-10-example-1.input b/2020/day-10-example-1.input deleted file mode 100644 index cd1b40b..0000000 --- a/2020/day-10-example-1.input +++ /dev/null @@ -1,11 +0,0 @@ -16 -10 -15 -5 -1 -11 -7 -19 -6 -12 -4 \ No newline at end of file diff --git a/2020/day-10-example-2.input b/2020/day-10-example-2.input deleted file mode 100644 index be5c492..0000000 --- a/2020/day-10-example-2.input +++ /dev/null @@ -1,31 +0,0 @@ -28 -33 -18 -42 -31 -14 -46 -20 -48 -47 -24 -23 -49 -45 -19 -38 -39 -11 -1 -32 -25 -35 -8 -17 -7 -9 -4 -2 -34 -10 -3 \ No newline at end of file diff --git a/2020/day-10.input b/2020/day-10.input deleted file mode 100644 index 4ec86f2..0000000 --- a/2020/day-10.input +++ /dev/null @@ -1,103 +0,0 @@ -153 -69 -163 -123 -89 -4 -135 -9 -124 -74 -141 -132 -75 -3 -18 -134 -84 -15 -61 -91 -90 -98 -99 -51 -131 -166 -127 -77 -106 -50 -22 -70 -43 -28 -41 -160 -44 -117 -66 -60 -76 -17 -138 -105 -97 -161 -116 -49 -104 -169 -71 -100 -16 -54 -168 -42 -57 -103 -1 -32 -110 -48 -12 -143 -112 -82 -25 -81 -148 -133 -144 -118 -80 -63 -156 -88 -47 -115 -36 -2 -94 -128 -35 -62 -109 -29 -40 -19 -37 -122 -142 -167 -7 -147 -121 -159 -87 -83 -111 -162 -150 -8 -149 \ No newline at end of file diff --git a/2020/day-10.ts b/2020/day-10.ts deleted file mode 100644 index e65522a..0000000 --- a/2020/day-10.ts +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -import { qs } from '../utils'; - -function makeKey(queue: number[]): string { - return queue.join('-'); -} - -function countArrangements(queue: number[], cache: Record, indent = ''): number { - // We want to start at the first item, and see how many options we have - // And then ... run through each of these - const options: number[][] = []; - const first = queue[0]; - for (let i = 1; i < queue.length; i++) { - const second = queue[i]; - if (second - first > 3) { - // Ok, this doesn't work anymore - break; - } else { - // Possible option - options.push([first, second, ...queue.slice(i + 1)]); - } - } - // For each of these options we now know that the first two entries are fixed, and we - // need to recurse on the third-and-following one - let arrangements = 0; - for (const option of options) { - const newQueue = option.slice(1); - if (newQueue.length < 2) { - // Reached the end with this option - arrangements++; - } else { - const key = makeKey(newQueue); - const cachedArrangements = cache[key]; - if (typeof cachedArrangements !== 'undefined') { - arrangements += cachedArrangements.value; - cachedArrangements.hits++; - } else { - const newArrangements = countArrangements(newQueue, cache, indent + ' '); - cache[key] = { value: newArrangements, hits: 0 }; - arrangements += newArrangements; - } - } - } - return arrangements; -} - -function processInput(input: string) { - const rl = createInterface(createReadStream(input)); - - // Start with the outlet (joltage of 0) - const joltages: number[] = [0]; - - rl.on('line', line => { - const joltage = Number(line); - const insertAt = -(qs(joltages, joltage) + 1); - joltages.splice(insertAt, 0, joltage); - }); - rl.on('close', () => { - console.log(`Results for ${input}:`); - - // Add the actual device adapter - joltages.push(joltages[joltages.length - 1] + 3); - - // Adapters need to fit, and we need to use all ... so this is merely a question - // of what are the differences between these values. - const diffs: number[] = []; - let diffOne = 0; - let diffThree = 0; - for (let i = 1; i < joltages.length; i++) { - const diff = joltages[i] - joltages[i - 1]; - diffs.push(diff); - if (diff === 1) { - diffOne++; - } else if (diff === 3) { - diffThree++; - } else { - throw new Error(`Found an unexpected diff of ${diff}`); - } - } - console.log(`${diffOne} of 1, ${diffThree} of 3: ${diffOne * diffThree} [${diffs}]`); - - console.log(`Input: ${joltages}`); - const cache: Record = {}; - const arrangements = countArrangements(joltages, cache); - console.log(`Arrangements: ${arrangements}`); - console.log(`Cache: ${JSON.stringify(cache, undefined, 2)}`); - }); -} - -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example-1.input`); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example-2.input`); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}.input`); \ No newline at end of file diff --git a/2020/day-11-example.input b/2020/day-11-example.input deleted file mode 100644 index ff5431a..0000000 --- a/2020/day-11-example.input +++ /dev/null @@ -1,10 +0,0 @@ -L.LL.LL.LL -LLLLLLL.LL -L.L.L..L.. -LLLL.LL.LL -L.LL.LL.LL -L.LLLLL.LL -..L.L..... -LLLLLLLLLL -L.LLLLLL.L -L.LLLLL.LL \ No newline at end of file diff --git a/2020/day-11.input b/2020/day-11.input deleted file mode 100644 index 99b103a..0000000 --- a/2020/day-11.input +++ /dev/null @@ -1,97 +0,0 @@ -LLL.LLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL..LLLLLLL..LLLLLLL.LLLL.LLLLLLLLLL -LLLLLLLLLLLLLLLL.LLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.L.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLL.LLLL.LLLLLLLLL.LLLLL.LLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLL.LLL.LLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLL -...L..L.L......LL.L.......L...L..LLL....L.LL.L..L.L.LL..L..L............LLL.L..L.L.L..LL.. -LLLLLLLLLLLLLLL..LLLLL.L.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLL.L.LLLLLL.LLLLLLLL -.LLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLL.LL.LLLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLL.LLLLLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLL.LLL -......L.L.L...LLL.LL...........L.....L..L...LL......L..L.L.L.....LL.LL..L..LL.LL......LLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLL.LLLLLL.LLLLLLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLL.L.LLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLL..LLLLLLLLLLLLLL -LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLL.L.LLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLLLLLLL.LLLLLLLLL.LLLLLLL..LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLL -L....LL.LL.....LLL.......L.....L.L..L.LL.L...L.L..L.....L...L....LL.LLL...L..L.LL.L..L...L -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LL.LLLL.LL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL..LLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.L -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLL.L.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLLLLLL.LLLLL.LL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLL.LLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLL.LLL -L....L......L..L..L.........L...LL..L..L.....L....L.LLL.L..L.LL..L..L..LL...L.......L.L... -LLLLLLLLLLLLLLLL..LLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLL.LL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLLLLLLLLLL..LLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLL.LLLL.LLLLLLL.LLLLLLLLL.LLL.LLLLLLLL.LLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLL..LLLLLLLLLLLL.LLLLLLLLLLLLL.LLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLL -L...LL..L..L..L.LL..L......L..L..LL.....LL...L...LL..L.L........LL.LL..LL.L......L..L..L.. -LLLLLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL..LLLLLL.LLLLLL...LLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLL.LLL.LLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLL.LLLLLLLL -LLLLLLL.LLLLLL.L.LLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL..LLLLLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -..............L.....L..L..L..L...L......L...LL...................LLLLL..L.LL...L.....L.L.. -LLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLL.LL.LLL.LLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLL..LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLLL.LLLLLLLLLL.LLLL.LLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLL -L.....L..L...LL...L.L...L..L.....L..L...L....L...L...LL...L......LL..L..LL.L.L..L.L.L.L.L. -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL..LLLLLL.LLLLLLLL.L.LLLL.LLLLLLLL -LLLLLLL.LLLLLL.L.LLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLL -LLLLLL.LLLLL.LLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLLLLLLLLLLLLLLLLLL..LLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL..LLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLL -LLL..L.L.....L.....LL.L..LL.L.L......L..L.L...L.L....L.....LL..LL.L......L...L....L...L... -L.LLLLLLLLLLL.LL.LLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLLL.LLLLLLL.LLL.LLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLL.L.LLLLLLL.LLLLLL.LL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLL.LLLLLL.LLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLL..LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL -.LL.....L.L.L...L.L.....L..L..LL....LLL.......L.L.......LL...LLL...L...L...LLL.L...LLLL..L -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLL..LLLLLLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLL.LLL.LLLLLLL.LLL.LLLLL.LLLLLLL.LLLLLLLL.LL.LLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLLLLLLLLLLL.LLL.LLL.LLLLLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.L.LLLLLL.L.LLLLLLLLLLLLL -LLLLLLL.LLLLLL.L.LLLLLLL.LLLL..LLLLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLL.L.LLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LL.LLLLLLLLLLLLLL.LLL.LLLL.LLLLL..LLLLLLLL -.L..LLL..L..LL...L.L..L......L.L.L..L.....L.....L..L....LLL....L.......L.LLL..LL....L..L.L -LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LL.LLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LL.LLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLL.L.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LL...L.L.L..L.L..........L..L..LL.LL....L.L.L.L.LLL.......L.......L.L....L...L..LL........ -LLLLLLLLLLLL.LLL.LLLLLLLLLLLL.LLLLLLLLL.LLLL..LLLLLLLLLL....LLLLLLLLLLLLLL..LLLLLLLLLLLLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLL.LL.LLLLLLLLLLLLLLL.LLLLLLLL -LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLL -LLLLLL.LLLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.L.LLLLL.LLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLL..LLLL.LLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLL -LLLLL.L.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLLLLL.LLLLLLLLLLL.L.LLLLLL.LLLLLLLL -.LLL..L...L.L......LL.L..LL.LL.LLLLL...L...LLLL.L..L..LLL......L...LL.....L..LLLL.LL.LL..L -LLLLLLL.LLLLLLLLLLL.LLL..LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLL.LL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.L.LLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLL.LLL -L...L.......L..LLLL..L.LL...LL....L.....L.L..L...LLLLL.....LL.....L.L.LLL.L..L.LL.....L.L. -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLL.LLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLL.LL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL..L.LLLLLLLLLLLLLLL -L.LLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLL.L.LLLLLLLLLLLL.LLLLLLLLLLLLLLL.L.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLL.LLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLL.LLLLLLLL.LLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLL.LLLLLLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLL.L -LLLLLLL.LLLLLLLL.LLLLLLL.LLLL..LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL..LLLLL.LLLLLLLL -LLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.LL.LLLLLLLL.LLLLLLLLLLLLLLL -LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLLL. -LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLLLL.LL.LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLL \ No newline at end of file diff --git a/2020/day-11.ts b/2020/day-11.ts deleted file mode 100644 index b9b8bff..0000000 --- a/2020/day-11.ts +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -import { between } from '../utils'; - -type State = '.'|'L'|'#'; - -const adjacency = [ - [-1, -1], [-1, 0], [-1, 1], - [ 0, -1], [ 0, 1], - [ 1, -1], [ 1, 0], [ 1, 1], -]; - -type GetNeighborOccupancy = (field: State[][], i: number, j: number) => number; - -function getNeighborOccupancyPart1(field: State[][], i: number, j: number): number { - return adjacency.reduce((result, [di, dj]) => { - const newI = i + di; - const newJ = j + dj; - if (between(newI, 0, field.length - 1) && between(newJ, 0, field[i].length - 1)) { - return result + (field[newI][newJ] === '#' ? 1 : 0); - } else { - return result; - } - }, 0); -} - -function getNeighborOccupancyPart2(field: State[][], i: number, j: number): number { - let count = 0; - for (const [di, dj] of adjacency) { - let ni = i + di, nj = j + dj; - while (between(ni, 0, field.length - 1) && between(nj, 0, field[ni].length - 1) && field[ni][nj] === '.') { - ni += di; - nj += dj; - } - - if (between(ni, 0, field.length - 1) && between(nj, 0, field[ni].length - 1) && field[ni][nj] === '#') { - count++; - } - } - return count; -} - -function iterate(field: State[][], getNeighborOccupancy: GetNeighborOccupancy, dieAtOrAbove: number): { newField: State[][], changes: number } { - const newField: State[][] = []; - let changes = 0; - - const rowLength = field[0].length; - for (let i = 0; i < field.length; i++) { - const newRow: State[] = []; - for (let j = 0; j < rowLength; j++) { - const current = field[i][j]; - if (current === '.') { - newRow.push('.'); - continue; - } - const occupied = getNeighborOccupancy(field, i, j); - if (current === 'L' && occupied == 0) { - newRow.push('#'); - changes++; - } else if (current === '#' && occupied >= dieAtOrAbove) { - newRow.push('L'); - changes++; - } else { - newRow.push(current); - } - } - newField.push(newRow); - } - return {newField, changes}; -} - -function logField(field: State[][]) { - field.forEach(row => console.log(row.join(''))); -} - -function processInput(input: string) { - const rl = createInterface(createReadStream(input)); - - const initialField: State[][] = []; - const cases = [ - { getNeighborOccupancy: getNeighborOccupancyPart1, dieAtOrAbove: 4 }, - { getNeighborOccupancy: getNeighborOccupancyPart2, dieAtOrAbove: 5 }, - ]; - - rl.on('line', line => { - // Process `line` here - initialField.push(Array.from(line) as State[]); - }); - rl.on('close', () => { - console.log(`Results for ${input}:`); - for (const {getNeighborOccupancy, dieAtOrAbove} of cases) { - let round = 1; - let field = initialField; - let result; - logField(initialField); - do { - result = iterate(field, getNeighborOccupancy, dieAtOrAbove); - field = result.newField; - logField(field); - console.log(`Changes after round ${round}: ${result.changes}`); - round++; - } while (result.changes > 0); - - // Count the number of occupied seats - const seats = field.map(row => row.reduce((cnt, state) => cnt + (state === '#' ? 1 : 0), 0)).reduce((cnt, rowCount) => cnt + rowCount, 0); - console.log(`Occupied ${getNeighborOccupancy.name}: ${seats}`); - } - }); -} - -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example.input`); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}.input`); diff --git a/2020/day-12-example.input b/2020/day-12-example.input deleted file mode 100644 index 48c2a50..0000000 --- a/2020/day-12-example.input +++ /dev/null @@ -1,5 +0,0 @@ -F10 -N3 -F7 -R90 -F11 \ No newline at end of file diff --git a/2020/day-12.input b/2020/day-12.input deleted file mode 100644 index d50617f..0000000 --- a/2020/day-12.input +++ /dev/null @@ -1,776 +0,0 @@ -R180 -E1 -N1 -R90 -E4 -F84 -W3 -F19 -E5 -N1 -W5 -W4 -R90 -S1 -F70 -R90 -W2 -S3 -L180 -E2 -R90 -E1 -R90 -N2 -E3 -F55 -W3 -R90 -S2 -E4 -L90 -F33 -W4 -S3 -F11 -N4 -W4 -F88 -W3 -F62 -L90 -S3 -W3 -N1 -E3 -E2 -N1 -E3 -S3 -E5 -S4 -W5 -L90 -W5 -R90 -E4 -F36 -N4 -E4 -E5 -F47 -R90 -N3 -E3 -L180 -S5 -R90 -S5 -W2 -S3 -F43 -W2 -R180 -W2 -S2 -L180 -E2 -F49 -L90 -F77 -S5 -E1 -S2 -F39 -L180 -F12 -W1 -L90 -F60 -S2 -E3 -N1 -E5 -R90 -E1 -N4 -W4 -S4 -E2 -L90 -F100 -E3 -F58 -S2 -E4 -F83 -W3 -N1 -R90 -F99 -W5 -W4 -F19 -N3 -W1 -W5 -F70 -R180 -R90 -F58 -E5 -N3 -R90 -N4 -F86 -N4 -F70 -L90 -F36 -R90 -S4 -R180 -N5 -F81 -W5 -R90 -E5 -L90 -F73 -S5 -E3 -N1 -F27 -E2 -N3 -L180 -W2 -F24 -N2 -L90 -F69 -N2 -E3 -F49 -L90 -S4 -W5 -F18 -R180 -F62 -S2 -F65 -E3 -F100 -N1 -F96 -W1 -F75 -L180 -W2 -S2 -F93 -E5 -S3 -R90 -S2 -F34 -R90 -F83 -S1 -W1 -F58 -L180 -N4 -E1 -R90 -W2 -F93 -S3 -F20 -R90 -N3 -E3 -N3 -L90 -F8 -S3 -F18 -S3 -N2 -F6 -L270 -F70 -W5 -S3 -F54 -E2 -F75 -E3 -R90 -N2 -W3 -L90 -E4 -F58 -N5 -F97 -W2 -L90 -W5 -S2 -W1 -S5 -F85 -N1 -E1 -N4 -E4 -L90 -E1 -R90 -S5 -L180 -R270 -N1 -L90 -E4 -N3 -F45 -N2 -F68 -R90 -F36 -N5 -F82 -S5 -E4 -R180 -S2 -L180 -N3 -R270 -W5 -F70 -L90 -W5 -F80 -W4 -N2 -R90 -S3 -W1 -F23 -N1 -W1 -N4 -F70 -S3 -L180 -F57 -R90 -L90 -F55 -L90 -N4 -F87 -L90 -F1 -L270 -F17 -N5 -R180 -F84 -R90 -W5 -F7 -W1 -S1 -E3 -F46 -S5 -E2 -F23 -R90 -E4 -W2 -F96 -E5 -L90 -F65 -F3 -S5 -E5 -N3 -W4 -L90 -S2 -F57 -E1 -R90 -F68 -E3 -L90 -W1 -F29 -N5 -W5 -N1 -F95 -N1 -L90 -F31 -S5 -L180 -N2 -W5 -R90 -F27 -E1 -R90 -E3 -S5 -F10 -R90 -N4 -E2 -F25 -S4 -E5 -F51 -N3 -W2 -L90 -S3 -L180 -F17 -E4 -F93 -E3 -L90 -F41 -L90 -S5 -L90 -W5 -N1 -F81 -L90 -E4 -W2 -R90 -W1 -S5 -R90 -F39 -W3 -R90 -N5 -E1 -L90 -F82 -S3 -R90 -W4 -F66 -F4 -L90 -F77 -R90 -E1 -L90 -F53 -S4 -F35 -W1 -F64 -R90 -F9 -S1 -E1 -L90 -W4 -R90 -S2 -W5 -R90 -S4 -L90 -N3 -F8 -L180 -N5 -E5 -N4 -F35 -N5 -W1 -N1 -E5 -F15 -R180 -F92 -W3 -L90 -F4 -L90 -E1 -S3 -W3 -R90 -F37 -N5 -F19 -S2 -F98 -L90 -F24 -W3 -F68 -N5 -R90 -W3 -L90 -W3 -L90 -S1 -L90 -S4 -W3 -F56 -N4 -R90 -E3 -W1 -L90 -E4 -N3 -R180 -E1 -S1 -W2 -R90 -N3 -F82 -N2 -F37 -S3 -L180 -E2 -L180 -F6 -N2 -F96 -E2 -R180 -E2 -W3 -R90 -E2 -S5 -S1 -F23 -R90 -W5 -F75 -S1 -L90 -S3 -E1 -F83 -W4 -L180 -W5 -L90 -N1 -E1 -S2 -F17 -L90 -S2 -F53 -R90 -S3 -N3 -W1 -N4 -L180 -L90 -E3 -F9 -S5 -F24 -W3 -E5 -N2 -F73 -N1 -F28 -N2 -W4 -N3 -F53 -E5 -F47 -W2 -F60 -L90 -E2 -F19 -S1 -F63 -W5 -F100 -N3 -L180 -F83 -N4 -W5 -F37 -S1 -F50 -E1 -N2 -W3 -R90 -F85 -S4 -F72 -N4 -L90 -F48 -R90 -F99 -R90 -F58 -W3 -W4 -F64 -E1 -R90 -F74 -L90 -F23 -N3 -N3 -E1 -S1 -W5 -L180 -F98 -L90 -F36 -W4 -S2 -W3 -F9 -F72 -W5 -F78 -N2 -F65 -S3 -F47 -S5 -R90 -F68 -L180 -W2 -F7 -E2 -E3 -S4 -R90 -N2 -L180 -W2 -R180 -E4 -R90 -W3 -L90 -E4 -F54 -L180 -E2 -F6 -W5 -F82 -E4 -R90 -E4 -F25 -N2 -R270 -N4 -F18 -N5 -R90 -S3 -R90 -F38 -R90 -F97 -W4 -F85 -S4 -F56 -E4 -S1 -F40 -W3 -F52 -L90 -F76 -N4 -F15 -S2 -F22 -S5 -L180 -F91 -L180 -F8 -L90 -E4 -N4 -F67 -L90 -S3 -R180 -R90 -N4 -F71 -W3 -F34 -E2 -N1 -F43 -W5 -L180 -N5 -W2 -F42 -R90 -W3 -F39 -E1 -S2 -L180 -N5 -E3 -N5 -F28 -E1 -R90 -S3 -F40 -L90 -S2 -S2 -L90 -W5 -L90 -F93 -R180 -W4 -S4 -W4 -F100 -S3 -R90 -E2 -L180 -W1 -E3 -S5 -L90 -F87 -N1 -R90 -F3 -R90 -E5 -R90 -S3 -F45 -L90 -S2 -F42 -R90 -F95 -L90 -E1 -N3 -R90 -F73 -S3 -E1 -L90 -S2 -E3 -L90 -L270 -F38 -S5 -R90 -F42 -L90 -N1 -F7 -S3 -F65 -N2 -F42 -L180 -W5 -S4 -E4 -F65 -S4 -E5 -F51 -E4 -R180 -F70 -R90 -F28 -N5 -W5 -N1 -F96 -L90 -W4 -S3 -W3 -F89 -W1 -L90 -F75 -L270 -S3 -R90 -L90 -F7 -E2 -F24 -R180 -S2 -L180 -F48 -R90 -F37 -W2 -R90 -W4 -L90 -W3 -F81 -E4 -N2 -F39 -E4 -N1 -W1 -L90 -F59 \ No newline at end of file diff --git a/2020/day-12.ts b/2020/day-12.ts deleted file mode 100644 index 3632503..0000000 --- a/2020/day-12.ts +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -type Command = 'N'|'E'|'S'|'W'|'F'|'R'|'L'; - -interface Point { - x: number; - y: number; -} - -interface State { - ship: Point; - waypoint: Point; -} - -function rotate({ x, y }: Point, turnsRight: /* -4<=turnsRight<=+Inf */ number): Point { - let nx = x; - let ny = y; - for (let i = 0; i < (turnsRight + 4) % 4; i++) { - const tmp = nx; - nx = ny; - ny = -tmp; - } - return { - x: nx, - y: ny, - }; -} - -function updateStatePart1(state: State, command: Command, argument: number): State { - let { ship, waypoint } = state; - - switch (command) { - case 'N': - ship.y += argument; - break; - case 'E': - ship.x += argument; - break; - case 'S': - ship.y -= argument; - break; - case 'W': - ship.x -= argument; - break; - case 'F': - ship.x += waypoint.x * argument; - ship.y += waypoint.y * argument; - break; - case 'L': - waypoint = rotate(waypoint, -argument / 90); - break; - case 'R': - waypoint = rotate(waypoint, argument / 90); - break; - } - - return { ship, waypoint }; -} - -function updateStatePart2(state: State, command: Command, argument: number): State { - let { ship, waypoint } = state; - - switch (command) { - case 'N': - waypoint.y += argument; - break; - case 'E': - waypoint.x += argument; - break; - case 'S': - waypoint.y -= argument; - break; - case 'W': - waypoint.x -= argument; - break; - case 'F': - ship.x += waypoint.x * argument; - ship.y += waypoint.y * argument; - break; - case 'L': - waypoint = rotate(waypoint, -argument / 90); - break; - case 'R': - waypoint = rotate(waypoint, argument / 90); - break; - } - - return { ship, waypoint }; -} - -const CASES = [ - { initialState: { ship: { x: 0, y: 0 }, waypoint: { x: 1, y: 0 } }, updateState: updateStatePart1 }, - { initialState: { ship: { x: 0, y: 0 }, waypoint: { x: 10, y: 1 } }, updateState: updateStatePart2 }, -]; - -function processInput({ initialState, updateState }: typeof CASES[0], input: string) { - const rl = createInterface(createReadStream(input)); - - // Deep-clone the initial state - let state: State = JSON.parse(JSON.stringify(initialState)); - - rl.on('line', line => { - let command = line[0] as Command; - const argument = parseInt(line.substring(1)); - - state = updateState(state, command, argument); - console.log(`${input} ${updateState.name}: After ${line}: ${JSON.stringify(state.ship)} facing towards ${JSON.stringify(state.waypoint)}`); - }); - - rl.on('close', () => { - console.log(`${input} ${updateState.name}: Manhattan distance ${Math.abs(state.ship.x) + Math.abs(state.ship.y)}`); - }); -} - -processInput(CASES[0], `${basename(process.argv[1], extname(process.argv[1]))}-example.input`); -processInput(CASES[1], `${basename(process.argv[1], extname(process.argv[1]))}-example.input`); -processInput(CASES[1], `${basename(process.argv[1], extname(process.argv[1]))}.input`); diff --git a/2020/day-14-example-2.input b/2020/day-14-example-2.input deleted file mode 100644 index b4b4e06..0000000 --- a/2020/day-14-example-2.input +++ /dev/null @@ -1,4 +0,0 @@ -mask = 000000000000000000000000000000X1001X -mem[42] = 100 -mask = 00000000000000000000000000000000X0XX -mem[26] = 1 \ No newline at end of file diff --git a/2020/day-14-example.input b/2020/day-14-example.input deleted file mode 100644 index fa0dd0a..0000000 --- a/2020/day-14-example.input +++ /dev/null @@ -1,4 +0,0 @@ -mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X -mem[8] = 11 -mem[7] = 101 -mem[8] = 0 \ No newline at end of file diff --git a/2020/day-14.input b/2020/day-14.input deleted file mode 100644 index 554e77b..0000000 --- a/2020/day-14.input +++ /dev/null @@ -1,554 +0,0 @@ -mask = XX001001X10X110X0001111001110X110101 -mem[3250] = 4436 -mem[48892] = 14455 -mem[25137] = 1097 -mem[57377] = 5760 -mem[25785] = 20344 -mem[54660] = 1936 -mask = 100110X00X0X11010101110110X00001XX0X -mem[20413] = 182815763 -mem[49549] = 9522935 -mem[29920] = 32420282 -mem[63511] = 9773 -mem[59685] = 980 -mask = 1110000111001X0100001011000X10X00X10 -mem[28709] = 2381953 -mem[53254] = 100644575 -mem[20622] = 1013234 -mem[46518] = 7512916 -mem[49118] = 39485 -mem[50666] = 8298665 -mem[58287] = 107999 -mask = 111000000110X1010010011XX100X0000001 -mem[12805] = 6015 -mem[20190] = 106469491 -mem[11123] = 8571 -mem[16350] = 3024 -mem[37958] = 29213622 -mask = 11000000011011010X01011011XX100011XX -mem[29717] = 194765 -mem[40119] = 1357487 -mask = 1X1000100X10X1000X01XX11000101011011 -mem[53311] = 5028191 -mem[38550] = 30559161 -mem[37724] = 446421839 -mem[27658] = 656376 -mem[36878] = 491 -mem[2514] = 711969106 -mem[8425] = 25352 -mask = 10101000X110X1X1000101X1000100011001 -mem[57587] = 156077909 -mem[8983] = 5589 -mem[21832] = 16170971 -mem[40748] = 14124 -mem[18993] = 3053 -mem[16438] = 2330074 -mask = 11100X000XX11X110001100000X0010111XX -mem[48379] = 719 -mem[8903] = 345168600 -mem[50733] = 6133 -mem[41283] = 24831 -mem[65183] = 84558 -mem[54817] = 98834 -mask = 1X10000X01X0110100X0X111000X00XX000X -mem[3941] = 450868 -mem[6069] = 2088 -mem[40200] = 2865 -mem[46518] = 5389 -mem[48814] = 19396 -mask = 01X0100X11111100100XX10X110110X0X001 -mem[20385] = 15270930 -mem[15395] = 13898910 -mem[19502] = 2459689 -mem[5270] = 61362490 -mask = 0100100111XXX100X0010100X111X0100X0X -mem[58709] = 17455712 -mem[14865] = 176745 -mem[2952] = 54766095 -mask = 111000X0X1001100010X11X0X01X00XX1011 -mem[39517] = 38586 -mem[38266] = 1003448 -mem[54660] = 154097 -mask = 1X0X00X00110110100011111100X01010111 -mem[4521] = 360234 -mem[10967] = 699075 -mem[34096] = 89 -mem[21340] = 3018 -mem[12820] = 24007 -mem[46518] = 1732 -mask = 010X10XX0110111XX0000X0X10111000011X -mem[37473] = 213255 -mem[17466] = 126749 -mask = 11XX0010110X1X0001X11001X11001001X11 -mem[34419] = 4401033 -mem[51972] = 547595351 -mem[29267] = 2460627 -mem[39192] = 15067 -mask = 11X0X0000110111XXXX1011010X000X11101 -mem[51442] = 31937 -mem[16518] = 7405326 -mem[63834] = 1488732 -mem[26265] = 1190 -mask = 01001X01110110X110XX0X010X100X110X00 -mem[8150] = 41274 -mem[9998] = 26361 -mem[2495] = 198393 -mem[25041] = 6310180 -mem[5890] = 20465 -mask = 1XXX00100110110000011X0101XX0100XX10 -mem[26607] = 1384959 -mem[58709] = 31743 -mem[8993] = 56827 -mem[53062] = 258857 -mem[21305] = 672194 -mask = 10XX100X01101X11X0X1001001X01X110X10 -mem[55577] = 128659409 -mem[19002] = 845525 -mem[14584] = 8317876 -mask = 11X0X00X010011XX000X1X100X110X010101 -mem[9998] = 494334359 -mem[592] = 950827 -mem[13221] = 8704 -mem[23131] = 29048231 -mask = 1110X0X10100110100X0100X01010010000X -mem[18567] = 243296 -mem[27202] = 304731 -mem[24869] = 25916650 -mem[57135] = 23996 -mask = 110001XX11001101100001XX00X111110010 -mem[34304] = 84360 -mem[31615] = 3771 -mem[34225] = 3477 -mem[58931] = 2972 -mask = 010X100XX1001X0111001000X011X1000100 -mem[27987] = 8009299 -mem[1668] = 99817 -mem[55978] = 39150409 -mem[26420] = 236757 -mask = 1X1000XX01011011X0X111X0010000101100 -mem[1117] = 280 -mem[4280] = 406684 -mem[31615] = 461997 -mem[17710] = 656126 -mem[19869] = 6759059 -mem[29930] = 25157555 -mask = 1XX01000011011110X0110011XX0XX1X1100 -mem[9998] = 158930980 -mem[56595] = 290347 -mem[62495] = 2154029 -mem[13139] = 240824 -mem[37955] = 1962062 -mem[59685] = 23811 -mask = 111000100X1X110100010100XX0X11X11001 -mem[61927] = 3404 -mem[53925] = 1029 -mem[4604] = 2697020 -mask = 10XXXXX0010X11010101110X1X0100X10011 -mem[36423] = 187983079 -mem[35715] = 28051066 -mem[60426] = 2732 -mem[13855] = 1771 -mem[31615] = 4663854 -mask = 1110X100X1111111X000X00000X010000001 -mem[4522] = 630 -mem[10122] = 1023763273 -mem[43180] = 53901 -mask = 010010110X0XX111100X00X000X00110X001 -mem[55120] = 9489901 -mem[44935] = 74420893 -mem[46825] = 517159 -mem[28078] = 312928319 -mem[15205] = 129861 -mem[4958] = 925787 -mem[3152] = 269 -mask = 11100X00110X1100010X1X1101011010X001 -mem[13451] = 3404810 -mem[27534] = 8632174 -mem[14401] = 3040 -mem[8542] = 3926892 -mask = X010000101001101000010110X00010X1X01 -mem[9740] = 117232 -mem[53779] = 32144 -mem[14267] = 62550 -mem[31615] = 1580737 -mem[8195] = 212112887 -mem[26629] = 300 -mask = 111001X10X0001000000X11001000X1010X1 -mem[36441] = 709 -mem[30737] = 11941 -mem[25335] = 184614 -mem[36260] = 901 -mask = 1001011001X0X10101011X0010000X000101 -mem[52419] = 1941048 -mem[50006] = 2164 -mask = 11100101010XX1X1101100101010X0001111 -mem[59199] = 40929064 -mem[45560] = 6749 -mem[16449] = 535 -mask = 01001001X11011XXX00X01X10111X01101X0 -mem[27668] = 115726141 -mem[34331] = 2819615 -mem[4631] = 1432 -mem[50121] = 101482650 -mem[27656] = 2138214 -mem[25426] = 491626 -mask = 010010X1X1XXXXX1100100000011X1100100 -mem[14401] = 92822 -mem[33872] = 479638 -mem[54211] = 32497707 -mem[61337] = 98669 -mem[50724] = 111542 -mask = XX0X1001111X11001X010000000X00101000 -mem[15715] = 1986 -mem[20256] = 81993455 -mask = 010X10011X011001100101X0X00101X0010X -mem[14131] = 6366 -mem[11512] = 119948 -mem[27055] = 2537 -mem[53483] = 4819251 -mem[43180] = 513 -mem[50965] = 28334 -mask = 100X100011001X0X0101X10X1X000X000110 -mem[34393] = 32931383 -mem[27316] = 22411579 -mem[9842] = 39791616 -mask = X101001001101XXX000X1101111101101011 -mem[39194] = 1039606 -mem[1043] = 19870767 -mem[43519] = 12559302 -mask = 1X000000010X1101X101111XX0X001XX0X11 -mem[32350] = 799729 -mem[16251] = 144705569 -mem[29478] = 252441 -mem[34509] = 132421118 -mem[38139] = 205501387 -mem[41867] = 1221 -mask = 1X1000010100X10X0000111110XXX0X01XX0 -mem[50371] = 55426 -mem[46715] = 237008 -mem[49071] = 29175 -mem[21421] = 301905 -mem[14865] = 182450 -mem[4521] = 431828838 -mask = X10X101111101011XX010XX0100100X000X1 -mem[16125] = 16228 -mem[29267] = 896900 -mem[33394] = 492137129 -mem[13125] = 29576953 -mem[15725] = 7205 -mem[14584] = 204223954 -mask = 11100001011X11010XX00111010X100X01X1 -mem[61082] = 450817865 -mem[26585] = 4330327 -mem[10154] = 17401 -mem[2580] = 204 -mask = 1X1XXX0101001X1000000010100101000011 -mem[33232] = 366048141 -mem[32350] = 262845291 -mem[11566] = 1065195 -mem[2881] = 4069871 -mem[50230] = 15284 -mask = 111X000101001100X11001X111110X00X0X0 -mem[4769] = 124213132 -mem[39679] = 31372778 -mem[49788] = 397 -mem[37380] = 125852 -mem[12731] = 1652900 -mem[50954] = 126510477 -mask = 101XX0000X0X11000101X10X110101X0011X -mem[42090] = 862 -mem[16720] = 830 -mem[54268] = 1964148 -mem[47479] = 43971 -mem[39495] = 242510335 -mask = 1X0000010100X11100X11101011111X1X101 -mem[53660] = 7408 -mem[59155] = 912 -mem[41194] = 3873 -mem[45140] = 150741374 -mem[2517] = 34604969 -mask = 1X011001111011001X01X1X0X011001X10X0 -mem[49361] = 1299 -mem[3338] = 250 -mem[19712] = 901211202 -mask = 10X100X101X0X101011011X1X1100XX0X001 -mem[17360] = 21666 -mem[12874] = 5813 -mem[29072] = 190751470 -mem[5281] = 107765 -mem[35992] = 10587613 -mem[27723] = 14464308 -mask = 1110X10001001111000X1010001001XX0011 -mem[37958] = 4007715 -mem[48168] = 1633 -mem[33037] = 1157056 -mem[51789] = 57397 -mem[15715] = 1173117 -mem[48835] = 147582 -mem[36664] = 16384131 -mask = X1100X000110110X0X0101X1100011010101 -mem[46968] = 5167575 -mem[19400] = 68398 -mem[22943] = 290141 -mem[33183] = 6398 -mask = 11000010X10X11000X0101010111100001X0 -mem[34426] = 1044218 -mem[23605] = 22524637 -mem[46715] = 90353789 -mem[47901] = 31588865 -mem[51647] = 5864 -mem[7817] = 5435304 -mem[51837] = 786823673 -mask = 11X010000XX01111XX011001X001X01011X1 -mem[57040] = 31166252 -mem[9242] = 8336389 -mem[27098] = 1346 -mem[59253] = 233889 -mem[18975] = 2608708 -mem[32618] = 186139 -mask = 010011XX110110001101X000X1110101010X -mem[7283] = 474 -mem[65183] = 17576835 -mem[15496] = 917 -mem[61222] = 354 -mem[17141] = 130253 -mem[36668] = 1713209 -mask = 11X00001011011010110XX1011X0X00000X1 -mem[7492] = 5456594 -mem[5028] = 5940 -mask = 010010110111000110001100X0X0011XX100 -mem[34509] = 317267839 -mem[11256] = 29196358 -mem[16438] = 695 -mem[37251] = 240270619 -mask = 1011X00101XX101100X1X01110XX1X011100 -mem[13870] = 10134037 -mem[19869] = 14129 -mem[40162] = 37930 -mask = 1X1000X001001100010111X1100X00001000 -mem[58709] = 11947856 -mem[35950] = 885104 -mem[34703] = 228034631 -mask = 11000X0X11101X0X1XX010X0011111100101 -mem[47331] = 14465 -mem[5333] = 257444 -mem[45140] = 482719 -mem[52463] = 2886 -mem[865] = 5635911 -mem[50116] = 1828 -mask = 1110X00101001101001X01X10101001XX101 -mem[1952] = 88398932 -mem[19656] = 542717423 -mem[37210] = 56544559 -mask = 101X000X0100X10000000011100X00011011 -mem[51972] = 174486661 -mem[54660] = 1063144 -mem[38089] = 103346160 -mask = 01X010010110111X1X0XX1X101XXX1110110 -mem[37724] = 554486 -mem[26754] = 184956326 -mem[29860] = 1351 -mem[992] = 36303 -mask = 111X010101001111X0X1XX100X1X11X00011 -mem[27208] = 4254 -mem[35726] = 9530 -mem[33400] = 54939 -mem[57377] = 36404 -mask = 1XX100X00101X101010111X0000110110011 -mem[19330] = 95529570 -mem[55888] = 7245735 -mem[13178] = 210652128 -mem[37957] = 8777 -mem[27055] = 4557 -mask = 11X0X0000X00X10100X010000X1X00X11001 -mem[28997] = 7527074 -mem[58911] = 3749437 -mask = 1010000101001XX000X0111X01111011XX01 -mem[50800] = 3045 -mem[8405] = 778 -mask = 10X1100XX10X110X0101110X10XX00X10111 -mem[8118] = 44193690 -mem[31080] = 6253993 -mem[51058] = 98518676 -mem[26420] = 444510 -mem[52332] = 773 -mem[43569] = 12978747 -mask = 110X00XX0101X1000001110X1110X0011011 -mem[40259] = 29595 -mem[27022] = 1047145 -mem[39212] = 1022111 -mem[44256] = 827 -mask = X0X0100X01101XX1000100100X1000X0XX00 -mem[46808] = 16282111 -mem[39194] = 17358 -mem[30519] = 15329 -mem[20210] = 89741114 -mem[43471] = 209821 -mem[26479] = 51192892 -mask = 01X01XX1010101X1X00X0X0110X000X00000 -mem[610] = 66868634 -mem[14693] = 1561 -mask = 01XX1X1101100001000XX001011111001X1X -mem[55624] = 1153 -mem[42873] = 95238952 -mem[52863] = 49132161 -mem[47893] = 4835 -mask = 11100X0X01XX1111000XX0000011000X1011 -mem[12004] = 371040455 -mem[8773] = 1811 -mem[24918] = 1494696 -mem[40159] = 423055 -mem[53311] = 8179367 -mem[4769] = 62185497 -mask = 10100010010X1101X10X11101100X000111X -mem[1028] = 1420 -mem[55933] = 939 -mem[52023] = 787 -mem[44935] = 31931 -mask = 101XX00X010111XX010XX11011000010X111 -mem[41496] = 35439 -mem[10603] = 5594 -mask = 0X0XX0011101010110X100111011XX00X101 -mem[20002] = 178 -mem[52106] = 14251319 -mem[39635] = 772 -mem[4453] = 14389 -mem[38406] = 61303502 -mask = XX0XX10111X0110110001XX00011010X0001 -mem[46208] = 200581589 -mem[17134] = 19364192 -mem[13554] = 180 -mem[1525] = 16657222 -mem[29930] = 88470 -mem[20027] = 26218 -mem[33212] = 3420 -mask = 100X000X01XX11X10X01X11100101XX11101 -mem[42427] = 3148 -mem[31191] = 34227921 -mem[5332] = 6209 -mask = 100000X00101X1011101011XX10001101011 -mem[588] = 105317709 -mem[58944] = 49932 -mem[41156] = 5686 -mem[52429] = 79254 -mem[39164] = 125502 -mem[58384] = 9863 -mask = 11XX100001001101010111X010X100XX001X -mem[55325] = 532371 -mem[10714] = 945 -mem[40811] = 831 -mem[52429] = 825 -mem[29287] = 871309 -mask = X1101001X11111001X00110011010011X01X -mem[5694] = 159997822 -mem[19902] = 7576 -mem[36358] = 23397 -mem[25700] = 8539929 -mem[3736] = 46206727 -mem[39212] = 59153 -mem[2356] = 1111 -mask = 1X1010XXX10011000000X100001101010101 -mem[47918] = 1863009 -mem[26437] = 2046435 -mem[24918] = 29543865 -mask = 1XXX0001011011010XX001100110100XXXX0 -mem[59155] = 12119 -mem[52] = 257262763 -mem[5137] = 620 -mem[14069] = 510285 -mem[45621] = 7565142 -mask = 110010X1010011010X01111X00X00X00011X -mem[19157] = 105432818 -mem[30121] = 19003 -mem[42427] = 14622666 -mem[17182] = 404866351 -mask = 0X001X11X0001X1110000100010011100101 -mem[50733] = 259882372 -mem[26223] = 36 -mem[24717] = 82286 -mem[27043] = 59822 -mask = 1X10X0X1010011X0000001110011101X0X01 -mem[6273] = 14023 -mem[60272] = 1284478 -mem[15323] = 181763 -mem[10258] = 48496693 -mem[4604] = 1283 -mem[59253] = 1501 -mask = 1X10X00001X011X101X111X11X0XX0011111 -mem[52632] = 827829147 -mem[61514] = 896166427 -mem[39212] = 7083 -mask = 0100X011011000011XX1010100X101000110 -mem[46696] = 3938 -mem[30717] = 486164 -mem[50113] = 1183 -mem[55797] = 7813 -mem[35980] = 2864 -mem[42957] = 1731 -mem[12885] = 5877830 -mask = 111X00X1XXX011010X0001100X0100100110 -mem[53412] = 1122 -mem[3544] = 1936 -mask = 010010X1011X00X1XX0X100100X01XX00011 -mem[26404] = 129912657 -mem[42427] = 8283676 -mem[49540] = 225057700 -mask = 111000000X10111101111101X000XX01100X -mem[6581] = 15005 -mem[34987] = 1525 -mem[53399] = 4281310 -mask = 01001X01110X1X0X1X0X1XX00101X0110000 -mem[23101] = 1016018 -mem[8773] = 15572 -mem[41940] = 86213860 -mask = 1XX000X001X0110X0X011111XX010X011111 -mem[12004] = 4210 -mem[57042] = 18456 -mem[4521] = 345391317 -mem[59155] = 2065415 -mem[55543] = 832584 -mem[25785] = 358916 -mem[30737] = 3867770 -mask = 0100100X0110110X000101100X1101X11001 -mem[7028] = 1311 -mem[26146] = 15688934 -mem[45948] = 11724085 -mem[24060] = 7928 -mem[47218] = 6801 -mem[3544] = 1164 -mask = 010XX011011000110X0010X1010X10011001 -mem[27498] = 49 -mem[46338] = 7293 -mem[63695] = 2760 -mem[26607] = 570024 -mem[386] = 305561631 -mask = 11100X01X100010000X01110111XX10110X1 -mem[5811] = 21737791 -mem[64396] = 31213894 -mem[3250] = 73337 -mem[61337] = 54481 -mem[36423] = 25022 -mem[25426] = 14959 -mem[4801] = 1704 -mask = 1110000101X0X10X0X1011XX0101X00001X0 -mem[3844] = 952254 -mem[60487] = 6495 -mem[42029] = 18562446 -mem[7631] = 6846 -mem[9377] = 93575 -mask = 1110000001X01XX10001X110000X1X101101 -mem[10374] = 550602 -mem[5332] = 339 -mem[38039] = 1028545 -mask = 1101001001X0110XX001X1XX101101011011 -mem[58473] = 143 -mem[47893] = 122 -mem[64544] = 6555692 -mem[22943] = 23337528 -mem[55147] = 889075 -mem[35980] = 24521 -mask = 101X0001010X111000001XXX01X00111X101 -mem[23886] = 248921 -mem[29588] = 352528 -mem[48835] = 518717801 -mem[51363] = 892 \ No newline at end of file diff --git a/2020/day-14.ts b/2020/day-14.ts deleted file mode 100644 index b171872..0000000 --- a/2020/day-14.ts +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -function maskToString(mask: bigint): string { - return mask.toString(2).padStart(36, '0'); -} - -type Address = bigint; -type Value = bigint; - -const BANK_SIZE = 1048576; - -abstract class Decoder { - // Banked memory - private readonly memoryBanks: Value[][] = new Array(); - - constructor( - public readonly name: string, - protected readonly bankSize: number = BANK_SIZE, - protected readonly debugEnabled: boolean = false, - ) {} - - public get sum() { - let lastProgress = 0; - const banks = this.memoryBanks.length; - return this.memoryBanks.reduce((r, bank, i) => { - if (this.debugEnabled) { - process.stdout.write(`\r...${i}/${banks} banks done: ${bank.length} bytes in this one`); - lastProgress = i; - } else if (lastProgress && i === banks - 1) { - process.stdout.write(`\r`); - } - return bank.reduce((bankSum, v) => bankSum + v, r); - }, BigInt(0)); - } - - public abstract opMask(mask: string): void; - public abstract opMem(address: Address, value: Value): void; - - protected memSet(address: Address, value: Value): void { - const bankIndex = Number(address / BigInt(this.bankSize)); - let bank = this.memoryBanks[bankIndex]; - if (!bank) { - bank = this.memoryBanks[bankIndex] = Array(); - } - - const bankAddress = Number(address % BigInt(this.bankSize)); - bank[bankAddress] = value; - } - - protected debug(...args: any[]) { - if (this.debugEnabled) { - console.debug(...args); - } - } -} - -export class DecoderV1 extends Decoder { - private orMask = BigInt(0); - private andMask = BigInt(parseInt('0xFFFFFFFFF')); - - constructor(bankSize?: number, debugEnabled?: boolean) { - super('V1', bankSize, debugEnabled); - } - - public opMask(mask: string) { - // Mask is an odd trinary thing, with '0'/'1' in a position setting the value at that bit position, and - // 'X' in a position to mean "unchanged" - // One could treat this single mask as two separate ones: Interpreting 'X'/'1' as 1 and '0' as 0 produces - // "AndMask", and 'X'/'0' as 0 and '1' as 1 produces the "OrMask". - // The final value then is (value & AndMask) | OrMask - this.andMask = BigInt(parseInt(mask.replace(/[X1]/g, '1'), 2)); - this.orMask = BigInt(parseInt(mask.replace(/[X0]/g, '0'), 2)); - this.debug(`mask = [AND = ${maskToString(this.andMask)}, OR = ${maskToString(this.orMask)}] {${mask}}`); - } - - public opMem(address: Address, value: Value) { - const maskedValue = this.applyMask(value); - this.memSet(address, maskedValue); - this.debug(`mem[${address}] = [${maskedValue}] {${value}}`); - } - - private applyMask(value: Value): Value { - return (value & this.andMask) | this.orMask; - } -} - -export class DecoderV2 extends Decoder { - private orMask = BigInt(0); - private floatMask = BigInt(0); - private floatingMasks = [BigInt(0)]; - - constructor(bankSize?: number, debugEnabled?: boolean) { - super('V2', bankSize, debugEnabled); - } - - public opMask(mask: string) { - // Process the value: - let newOrMask = BigInt(0); - // For each 'X' we add two masks: One where the 'X' is a 0, and one where it is a 1. - let newFloatingMasks = [BigInt(0)]; - let newFloatMask = BigInt(0); - - function invariants(allowZero: boolean, check: boolean) { - if (check) { - // Sanity check: We should have 2^popcnt(floatMask) unique floating masks, and at least 1 - const expectedFloatingMasks = 2 ** (newFloatMask.toString(2).match(/1/g)?.length || 0); - if (expectedFloatingMasks) { - if (expectedFloatingMasks !== newFloatingMasks.length) { - throw new Error(`unexpected number of floating masks`); - } - if (new Set(newFloatingMasks).size !== expectedFloatingMasks) { - throw new Error(`non-unique floating masks`); - } - } else if (!allowZero) { - throw new Error('must have at least one floating bit'); - } - } - } - - for (let i = 0; i < mask.length; i++) { - const c = mask[i]; - const bit = BigInt(1) << BigInt(36 - i - 1); - if (c === '1') { - // Set the bit in all existing masks - newFloatingMasks = newFloatingMasks.map(newMask => newMask | bit); - newOrMask = newOrMask | bit; - } else if (c === 'X') { - // Copy the masks and set the bit to one in the copies - newFloatingMasks = [ - // Masks where the bit stays 0 - ...newFloatingMasks, - // Masks where the bit is 1 - ...newFloatingMasks.map(newMask => newMask | bit), - ]; - - // Remember that this was a floating bit - newFloatMask = newFloatMask | bit; - } else { - // Nothing to do, bit was initialized to 0 - } - - invariants(true, this.debugEnabled); - } - - invariants(false, this.debugEnabled); - - this.orMask = newOrMask; - this.floatingMasks = newFloatingMasks; - this.floatMask = newFloatMask; - this.debug(`mask = [OR = ${maskToString(this.orMask)}, FLOAT = ${maskToString(this.floatMask)}, ${this.floatingMasks.length} floating] {${mask}}`); - } - - public opMem(address: Address, value: Value) { - const maskedAddresses = this.maskedAddresses(address); - for (const maskedAddress of maskedAddresses) { - this.memSet(maskedAddress, value); - } - this.debug(`mem[${maskedAddresses.length} addresses] = ${value}`); - } - - private maskedAddresses(address: Address): Address[] { - // Process the address: - // 1. Apply the orMask to all non-floating bits - const orMasked = BigInt(address) & ~this.floatMask | this.orMask; - // 2. Apply each of the floating masks to the floating bits - return this.floatingMasks.map(mask => orMasked | (mask & this.floatMask)); - } -} - -const STMT_RE = /^((mask) = ([X01]+)|(mem)\[(\d+)\] = (\d+))$/; - -function processInput(input: string, ...decoders: Decoder[]) { - const rl = createInterface(createReadStream(input)); - - rl.on('line', line => { - const match = STMT_RE.exec(line); - if (!match) { - throw new Error(`Invalid syntax: ${line}`); - } - - if (match[2] === 'mask') { - const maskValue = match[3]; - decoders.forEach(decoder => decoder.opMask(maskValue)); - } else if (match[4] === 'mem') { - const address = BigInt(match[5]); - const sourceValue = BigInt(match[6]); - decoders.forEach(decoder => decoder.opMem(address, sourceValue)); - } else { - throw new Error('ASSERTION: Cannot happen'); - } - }); - rl.on('close', () => { - decoders.forEach(decoder => { - console.log(`Results for ${input} and decoder ${decoder.name}: ${decoder.sum}`); - }); - }); -} - -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example.input`, new DecoderV1()); -// The initial example is "horrible" when using the v2 decoder, due to the amount of floating bits in the mask. -//processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example.input`, new DecoderV2()); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example-2.input`, new DecoderV2()); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}.input`, new DecoderV1(), new DecoderV2()); diff --git a/2020/day-15.ts b/2020/day-15.ts deleted file mode 100644 index c32a03b..0000000 --- a/2020/day-15.ts +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env node - -function processInput(input: string, turns: number): number { - const numbers = input.split(/,/).map(v => parseInt(v)); - - // Turns are counted 1,2,3,... - // That means the 2020th number spoken will happen in turn 2020. - // In terms of remembering what was spoken: The theoretically highest value could be the number of turns (if - // the value was spoken once in the beginning, and then on the last turn again), and therefore the number of - // entries is also at the most the number of turns. - // For the 30M case, and assuming a reasonable storage of numbers as 8 bytes (floating point double) we need - // at most 240MiB memory ... that's ok. - const lastSpokenAt: number[] = new Array(turns); - numbers.forEach((n, i) => { - lastSpokenAt[n] = i + 1; - }); - - // The next number spoken will be 0, as the one before that (numbers[numbers.length - 1]) - // will have been new. - let spoken = 0; - for (let i = numbers.length + 1; i < turns; i++) { - if (i % 10000 === 0) { - console.debug(`${input} turn ${i}: Spoken ${spoken}`); - } - const previousSpokenAt = lastSpokenAt[spoken]; - lastSpokenAt[spoken] = i; - if (previousSpokenAt) { - spoken = i - previousSpokenAt; - } else { - spoken = 0; - } - } - - return spoken; -} - -const cases = { - '0,3,6': [436, 175594], - '1,3,2': [1, 2578], - '2,1,3': [10, 3544142], - '1,2,3': [27, 261214], - '2,3,1': [78, 6895259], - '3,2,1': [438, 18], - '3,1,2': [1836, 362], -} - -for (const [input, expectedSpoken] of Object.entries(cases)) { - const turns = [2020, 30000000]; - for (let i = 0; i < turns.length; i++) { - const spoken = processInput(input, turns[i]); - if (spoken !== expectedSpoken[i]) { - throw new Error(`Failed in case ${input} after ${turns[i]} turns, got ${spoken} but expected ${expectedSpoken[i]}`); - } else { - console.log(`Case ${input} after ${turns[i]} turns: ${spoken}`); - } - } -} - -const input = '0,3,1,6,7,5'; -const resultPart1 = processInput(input, 2020); -console.log(`Case ${input} after 2020 turns: ${resultPart1}`); -const resultPart2 = processInput(input, 30000000); -console.log(`Case ${input} after 30000000 turns: ${resultPart2}`); diff --git a/2020/day-16-example.input b/2020/day-16-example.input deleted file mode 100644 index ba62efb..0000000 --- a/2020/day-16-example.input +++ /dev/null @@ -1,12 +0,0 @@ -class: 1-3 or 5-7 -row: 6-11 or 33-44 -seat: 13-40 or 45-50 - -your ticket: -7,1,14 - -nearby tickets: -7,3,47 -40,4,50 -55,2,20 -38,6,12 \ No newline at end of file diff --git a/2020/day-16.input b/2020/day-16.input deleted file mode 100644 index 2895e57..0000000 --- a/2020/day-16.input +++ /dev/null @@ -1,269 +0,0 @@ -departure location: 30-260 or 284-950 -departure station: 29-856 or 863-974 -departure platform: 32-600 or 611-967 -departure track: 44-452 or 473-965 -departure date: 36-115 or 129-950 -departure time: 50-766 or 776-972 -arrival location: 40-90 or 104-961 -arrival station: 40-864 or 887-971 -arrival platform: 32-920 or 932-964 -arrival track: 45-416 or 427-959 -class: 47-536 or 557-964 -duration: 33-229 or 246-969 -price: 25-147 or 172-969 -route: 32-328 or 349-970 -row: 50-692 or 709-964 -seat: 49-292 or 307-964 -train: 28-726 or 748-954 -type: 37-430 or 438-950 -wagon: 46-628 or 638-973 -zone: 39-786 or 807-969 - -your ticket: -89,193,59,179,191,173,61,73,181,67,71,109,53,79,83,113,107,139,131,137 - -nearby tickets: -499,362,657,143,723,763,935,454,473,586,372,489,214,753,765,65,307,56,853,934 -228,664,709,361,856,645,363,171,901,199,62,513,667,808,350,890,715,687,257,721 -531,490,628,88,947,252,832,917,686,571,362,874,837,588,849,140,655,407,90,611 -777,194,111,386,90,598,153,363,373,566,191,945,559,819,289,487,480,590,691,756 -186,366,196,844,655,659,845,109,355,330,71,176,397,380,822,776,369,447,658,949 -783,763,570,184,260,448,856,717,913,646,774,657,841,917,910,193,941,408,110,577 -378,832,670,59,155,911,209,74,57,947,144,514,411,89,690,856,854,286,597,132 -319,684,204,909,342,206,204,943,620,52,516,115,430,319,84,618,593,211,596,581 -66,146,910,225,107,112,918,679,255,757,125,946,863,892,78,525,373,913,87,838 -674,653,588,220,448,941,112,924,474,358,513,649,766,500,847,197,639,836,373,573 -76,115,776,726,598,361,480,772,356,129,506,380,202,810,932,756,408,81,786,889 -311,620,848,357,483,754,181,300,284,60,259,674,596,289,397,113,894,82,291,754 -84,600,751,223,595,478,198,2,402,428,355,517,947,933,624,59,598,711,752,513 -286,664,786,775,510,363,666,229,914,938,196,509,410,528,681,943,477,850,640,595 -365,17,624,375,640,483,208,258,189,222,889,655,852,326,109,428,758,616,889,288 -566,195,201,949,205,517,672,762,180,886,679,63,596,664,678,596,894,384,321,212 -576,316,480,579,925,328,498,194,191,132,106,863,210,416,351,663,643,218,366,942 -776,60,256,400,368,664,469,53,949,689,569,253,319,717,387,591,845,66,499,566 -620,831,379,712,614,176,682,666,83,197,438,916,535,504,218,377,627,155,429,855 -853,525,865,487,190,940,810,251,786,618,895,580,908,86,578,136,781,562,498,759 -671,625,256,592,177,500,523,50,443,692,650,128,441,832,626,491,252,405,661,756 -597,722,922,721,319,388,653,484,83,142,781,451,106,499,515,672,113,374,911,311 -211,716,176,715,627,286,327,531,566,587,916,431,57,371,894,677,778,193,710,447 -559,508,196,178,844,78,114,662,142,558,514,378,375,694,718,314,384,89,816,562 -290,578,105,478,229,260,752,496,187,937,137,898,69,399,980,638,441,84,589,574 -413,592,841,498,793,214,947,582,827,940,446,572,259,623,213,355,853,360,60,195 -481,764,308,384,131,247,595,756,221,361,175,256,407,255,155,752,781,524,403,640 -74,765,914,319,715,86,316,612,197,640,827,760,926,106,520,818,229,824,623,404 -576,504,694,379,75,528,638,257,482,852,837,563,575,389,686,217,852,684,314,184 -481,679,312,796,358,71,376,830,209,946,69,591,939,357,59,284,522,626,218,825 -355,812,691,377,833,938,139,233,643,764,663,692,722,576,495,843,450,536,359,174 -367,749,373,379,69,753,711,81,445,265,405,624,759,814,311,623,228,290,682,195 -475,841,833,415,13,809,478,70,191,228,934,760,765,508,398,655,907,850,487,54 -198,841,184,84,492,945,429,72,753,572,510,408,827,289,177,559,890,837,987,291 -427,198,192,666,319,369,565,861,512,216,81,899,388,761,683,933,529,515,673,674 -355,188,827,614,178,600,641,181,915,728,934,526,904,136,74,649,187,77,381,498 -751,317,780,190,897,781,65,852,933,69,657,811,517,564,842,877,382,84,56,576 -946,839,941,322,409,318,751,850,215,750,394,578,95,284,902,396,409,51,309,938 -54,400,54,307,290,665,125,507,220,600,214,405,864,217,763,284,382,820,129,910 -722,68,841,521,597,286,722,481,451,145,448,389,61,844,650,487,250,781,149,70 -175,323,322,831,857,137,616,686,408,175,709,903,214,917,414,108,367,827,684,593 -321,820,388,220,368,137,403,523,914,839,64,724,482,307,284,448,585,208,764,988 -86,926,414,213,825,682,473,67,318,144,51,311,814,709,520,687,623,396,949,387 -522,369,139,593,122,210,716,906,406,488,681,753,852,189,71,203,51,145,639,412 -322,368,18,663,903,574,203,363,391,643,205,474,182,517,855,486,890,315,725,82 -60,582,819,529,180,140,570,402,191,594,863,146,614,631,51,593,828,583,184,78 -856,622,291,412,503,532,563,217,404,352,349,406,675,277,292,765,748,493,691,626 -647,849,636,64,479,715,623,132,322,408,524,385,212,328,289,104,82,689,908,650 -197,444,249,763,892,86,775,441,172,664,379,596,910,584,574,376,665,899,174,847 -375,906,894,75,895,82,250,367,350,581,912,927,370,888,938,413,109,909,570,481 -104,831,565,413,849,533,861,394,361,511,292,573,567,218,832,135,717,851,134,223 -847,59,369,147,509,80,184,527,199,430,614,687,621,823,132,787,569,109,665,112 -109,983,680,682,191,65,139,643,687,228,828,317,211,784,851,757,672,64,616,173 -403,640,763,704,504,381,201,933,144,597,825,79,496,246,783,113,84,650,720,81 -356,82,615,375,222,361,182,255,112,845,612,298,891,887,382,839,380,691,405,660 -251,535,590,228,181,710,663,485,856,929,389,892,573,247,856,313,679,397,50,850 -895,673,675,513,838,181,135,696,599,327,583,720,486,104,691,777,115,536,724,920 -519,3,55,711,820,572,614,401,751,664,856,779,726,687,672,415,680,536,481,684 -692,781,22,72,586,906,845,356,852,590,777,372,593,579,369,663,619,317,134,138 -623,484,723,936,810,940,824,676,362,172,494,864,360,133,402,911,307,634,828,428 -899,308,410,558,557,452,69,84,65,5,187,849,493,223,441,349,499,677,67,915 -222,758,668,351,782,373,825,839,369,615,904,186,815,379,897,380,863,911,60,981 -576,710,508,63,506,888,638,476,626,616,863,494,434,898,715,759,946,208,932,84 -495,255,259,810,586,387,804,69,564,73,140,628,890,205,213,363,709,683,401,78 -79,582,688,536,114,106,622,289,395,417,786,384,175,55,850,855,327,189,135,254 -379,895,255,498,766,523,291,782,944,839,615,687,892,824,479,77,619,359,702,680 -250,144,611,936,220,851,509,379,260,821,532,859,79,673,906,624,211,780,349,448 -75,643,392,826,139,579,479,618,372,563,823,913,106,286,639,594,455,895,388,776 -370,785,939,918,661,841,582,655,678,109,850,673,423,864,290,677,762,834,383,686 -19,906,528,475,779,174,519,389,715,816,247,500,350,250,54,897,57,942,369,443 -114,684,251,944,56,944,228,217,666,778,650,605,488,284,643,516,754,561,659,938 -292,429,906,605,935,88,140,197,721,438,257,590,324,900,325,785,290,522,491,619 -249,52,649,558,605,914,494,286,373,132,892,766,709,355,655,321,218,473,906,562 -612,908,180,854,475,825,61,516,363,945,896,176,563,763,361,221,847,205,631,112 -936,57,379,279,534,211,889,254,198,381,645,764,318,377,619,850,78,750,181,83 -413,130,497,366,65,307,255,686,181,368,997,560,781,205,69,863,401,809,829,683 -137,227,53,486,826,676,221,896,219,358,981,370,638,528,649,404,482,942,809,676 -918,172,942,948,821,911,291,906,393,438,757,702,215,383,178,219,350,894,757,403 -526,913,180,376,653,617,837,935,896,373,343,184,257,660,784,406,901,904,377,689 -189,388,628,55,723,82,51,369,808,365,137,668,664,596,325,672,360,316,797,939 -88,905,90,284,619,394,326,415,836,891,618,207,754,226,766,572,444,567,177,991 -685,531,67,314,673,136,325,283,659,374,403,60,914,492,478,648,190,320,592,692 -137,146,504,678,691,247,673,438,999,315,639,536,917,416,212,187,896,198,785,452 -855,205,111,600,562,785,489,226,209,941,518,384,700,579,315,657,74,654,591,558 -444,360,672,367,819,108,757,136,621,838,323,785,478,809,492,376,161,508,901,586 -205,500,513,902,408,909,573,663,891,290,326,389,477,376,810,392,596,382,846,989 -141,366,489,481,716,350,589,63,655,558,451,143,289,594,866,933,711,63,213,380 -320,144,949,726,314,576,639,80,287,143,616,713,945,623,228,927,374,385,856,499 -215,135,351,409,69,619,658,639,567,716,227,888,768,66,115,320,77,718,748,369 -614,894,572,515,842,371,253,570,479,574,292,394,463,659,840,227,763,757,777,83 -401,887,116,854,751,683,137,898,104,649,596,779,935,65,570,220,147,850,781,379 -353,808,187,909,895,710,192,903,784,779,755,788,896,292,719,428,843,681,407,313 -83,722,826,829,392,616,655,484,520,720,53,243,145,360,63,594,512,443,850,200 -588,889,187,889,581,215,290,319,821,440,601,220,482,307,217,690,758,512,942,372 -722,183,134,843,807,783,509,657,411,859,561,401,763,719,756,380,756,375,443,207 -289,853,562,190,181,652,988,942,315,225,813,355,404,107,429,442,311,377,259,855 -527,780,526,323,449,218,721,714,84,200,806,717,619,587,821,399,570,518,778,893 -836,309,893,780,943,779,657,256,528,296,512,476,131,641,828,223,807,683,562,313 -855,192,440,557,427,710,776,755,653,920,191,763,631,664,897,580,845,916,659,66 -179,559,920,399,906,720,822,942,852,408,617,690,599,937,949,356,195,982,251,318 -942,990,386,328,473,669,52,324,531,889,854,322,594,762,536,135,672,501,612,229 -627,500,725,255,136,370,403,58,77,838,674,620,858,307,438,189,392,674,568,446 -529,415,438,661,287,511,200,250,179,388,596,582,176,529,514,978,945,106,312,564 -587,392,947,762,110,387,495,115,452,572,416,676,189,751,208,985,478,828,442,638 -439,935,614,357,919,131,385,247,674,113,835,766,908,373,134,257,996,487,145,836 -855,619,843,711,577,427,392,661,485,257,293,504,315,450,190,389,581,197,823,711 -617,816,838,636,257,58,935,668,501,386,226,838,919,660,755,643,438,216,526,753 -685,288,86,781,908,140,310,144,258,52,132,560,803,622,591,134,218,248,566,518 -782,290,896,384,324,452,671,562,508,653,475,996,683,624,494,597,145,682,67,910 -567,532,719,399,50,616,922,914,310,612,353,653,400,384,562,684,492,568,135,689 -170,749,486,901,108,825,887,210,519,226,762,188,590,903,452,617,615,834,363,517 -308,497,496,400,530,512,939,647,514,359,435,625,186,580,66,206,718,491,657,50 -558,698,326,195,809,89,135,378,518,846,692,204,716,573,176,369,583,752,227,651 -399,982,611,404,619,317,86,486,524,673,51,489,751,318,766,486,826,249,381,815 -597,856,16,375,61,137,906,888,439,669,782,893,902,398,785,900,671,319,710,136 -311,653,224,823,442,220,902,603,367,54,945,195,897,67,60,360,814,450,246,665 -358,579,849,813,315,308,825,681,827,114,857,352,481,440,212,944,836,312,501,439 -55,129,66,942,133,137,208,50,478,205,200,916,851,487,889,824,989,691,490,364 -308,381,688,440,135,516,816,504,287,625,750,355,663,714,176,391,229,989,904,284 -213,780,407,912,573,535,585,825,897,842,588,469,893,321,567,831,90,138,613,863 -853,119,581,373,84,761,217,640,752,383,226,650,357,322,438,503,292,559,291,492 -684,874,935,786,89,852,940,397,643,51,722,647,79,50,817,86,585,822,611,575 -777,890,911,915,114,452,635,204,79,289,310,449,628,247,358,948,894,307,350,893 -724,685,936,485,887,82,835,870,481,615,616,751,131,505,111,82,912,438,50,405 -520,826,224,592,411,284,834,668,902,657,661,897,758,369,933,809,704,501,222,777 -624,628,105,260,663,502,447,436,310,851,836,208,911,591,718,755,844,647,854,497 -762,175,201,4,644,111,427,490,713,409,531,143,577,75,287,663,172,411,911,57 -285,225,187,359,57,911,315,56,892,398,216,533,784,916,10,690,912,133,939,328 -754,649,519,319,315,807,640,749,668,404,594,514,175,587,637,582,188,90,219,427 -906,146,274,173,229,562,480,518,897,821,53,913,319,63,189,571,485,613,509,353 -502,646,58,352,505,660,575,133,671,811,586,350,850,802,474,360,911,136,564,753 -106,62,354,247,935,626,978,371,834,214,586,76,659,532,938,444,388,443,668,574 -132,473,368,718,80,754,751,947,903,772,284,256,650,258,251,682,197,619,758,501 -77,892,401,675,270,935,183,658,578,497,373,209,807,187,209,85,205,251,367,57 -750,209,834,811,665,898,361,64,114,685,258,943,644,532,129,614,924,76,377,405 -195,428,488,67,935,19,375,392,484,450,892,416,260,650,256,194,397,483,113,557 -474,852,196,427,375,977,639,643,536,785,66,452,326,623,828,309,909,373,138,113 -219,225,818,84,639,380,856,676,372,82,76,577,517,758,942,182,604,194,400,357 -908,622,568,81,183,901,868,354,818,835,894,430,482,824,856,839,190,77,88,840 -641,572,228,286,936,889,818,777,778,846,643,113,150,138,754,934,582,581,627,685 -898,891,841,0,62,908,110,888,74,831,286,653,407,138,653,932,514,853,357,598 -622,413,899,828,185,194,173,571,481,670,315,515,562,207,836,708,766,683,488,372 -248,457,934,372,564,414,662,665,949,642,202,144,189,842,214,592,374,888,211,247 -668,139,115,132,522,683,205,849,784,481,713,776,689,63,563,658,361,982,196,897 -289,407,60,434,323,561,196,319,517,846,686,855,173,864,611,814,717,618,313,687 -474,892,536,259,888,86,81,328,687,402,375,891,291,666,805,909,386,193,511,898 -131,210,638,840,392,765,565,841,394,781,813,562,316,145,526,528,826,803,87,197 -841,557,935,116,837,478,174,839,623,752,71,484,709,685,495,360,327,143,440,908 -452,86,411,358,847,632,853,716,410,491,934,86,196,598,600,486,402,212,493,714 -766,663,131,474,888,85,569,710,251,225,846,194,692,925,398,783,226,291,189,488 -657,560,388,477,509,87,139,911,258,671,947,753,865,913,324,638,366,526,584,429 -658,181,83,611,259,561,752,121,758,561,612,478,518,763,896,596,68,328,173,446 -625,810,62,508,458,355,847,896,220,838,933,536,376,112,427,190,511,403,479,675 -367,495,523,441,694,656,286,309,203,839,481,848,646,830,383,221,848,185,615,208 -311,526,497,750,473,916,393,396,564,191,479,723,627,182,444,484,173,754,661,8 -759,848,112,516,668,189,217,617,598,117,831,251,906,905,560,86,573,938,63,908 -188,889,534,86,999,187,441,186,762,61,827,106,222,756,814,113,716,54,200,808 -809,259,908,290,905,316,761,593,846,408,509,780,516,447,311,201,773,217,948,932 -210,253,621,481,900,557,318,379,909,511,985,904,681,716,115,70,214,385,825,427 -533,130,571,599,621,141,612,786,838,402,662,186,297,820,759,381,208,592,576,318 -320,253,349,831,394,557,105,752,522,191,181,891,200,13,409,762,833,317,683,55 -401,416,920,309,583,665,570,369,199,54,455,185,513,80,527,912,442,783,615,85 -365,190,504,219,595,618,593,350,782,809,66,919,427,474,406,137,81,14,189,442 -135,187,428,506,662,209,850,905,184,855,935,584,606,944,819,371,825,720,598,912 -622,620,408,224,530,792,894,855,372,667,653,820,514,180,479,685,190,196,107,560 -205,848,375,252,628,479,670,147,413,156,759,949,489,719,681,493,70,508,807,835 -776,676,62,512,658,477,215,748,911,186,500,557,213,862,905,373,677,250,410,250 -58,88,684,855,626,498,574,631,503,749,75,59,641,207,440,404,139,887,751,363 -113,186,66,204,104,726,115,137,617,832,90,755,664,517,452,635,594,749,892,363 -356,863,658,575,896,903,373,645,192,907,277,816,844,532,519,520,402,390,623,507 -83,514,383,674,628,832,584,723,639,307,144,569,191,199,990,718,76,415,193,756 -308,267,503,448,842,228,55,371,63,724,590,894,566,621,477,448,566,752,530,675 -569,327,379,64,84,51,273,863,721,501,592,688,406,814,498,292,505,487,901,398 -830,855,66,534,710,441,623,816,324,368,318,450,232,407,619,639,50,530,413,428 -477,579,480,721,16,713,673,53,687,256,624,444,534,725,653,227,76,750,411,104 -720,405,915,676,80,623,757,141,901,847,493,485,123,379,444,349,832,711,77,73 -528,50,913,528,50,61,354,489,838,600,193,387,382,621,191,822,119,82,211,836 -516,565,76,906,586,638,755,716,588,822,502,15,492,896,391,503,685,382,188,940 -318,583,260,677,873,822,364,255,624,624,147,721,63,218,215,567,136,493,87,511 -58,446,210,582,133,814,719,476,412,863,492,901,580,845,87,179,629,177,915,322 -112,712,386,667,624,369,650,317,177,230,532,56,360,482,479,818,893,835,258,495 -51,492,763,777,287,508,827,138,620,635,915,311,808,510,82,360,564,251,446,138 -198,678,855,410,568,899,712,442,173,438,18,86,777,83,752,144,207,721,587,590 -79,352,414,777,786,384,671,346,600,591,829,316,374,939,229,199,216,219,109,210 -508,154,508,677,510,212,529,903,758,410,199,131,88,476,481,508,825,393,784,287 -55,652,686,521,620,388,785,907,535,683,631,363,186,487,289,406,481,572,360,574 -133,507,413,366,838,939,131,589,678,440,520,912,142,533,909,17,588,753,833,657 -111,356,638,172,491,684,110,846,384,433,679,647,289,846,916,946,352,196,786,479 -567,224,907,310,488,763,195,139,595,512,687,680,493,401,130,749,273,353,498,679 -814,988,813,443,662,948,136,503,517,392,815,317,723,416,400,318,627,780,836,890 -328,196,856,288,623,257,525,285,679,512,564,170,723,534,916,179,67,651,557,834 -450,484,381,441,774,570,664,815,147,319,173,316,137,532,327,657,749,510,200,199 -902,650,327,258,647,667,250,77,579,598,723,473,510,364,923,369,493,357,318,359 -314,824,689,488,809,892,530,384,809,399,497,413,935,133,641,360,996,643,615,215 -365,756,249,585,913,613,821,353,646,851,411,54,710,153,289,199,617,200,383,528 -824,257,831,938,481,841,576,179,321,938,919,81,479,766,705,257,513,112,353,200 -71,748,208,75,250,319,498,179,997,394,409,764,377,678,534,320,113,512,669,115 -260,587,57,671,366,248,175,727,814,596,309,664,757,781,940,62,187,809,642,816 -406,205,569,108,817,414,366,474,86,311,901,682,589,256,283,814,393,596,856,321 -920,613,190,616,616,614,897,384,213,222,158,359,80,837,140,709,854,356,838,820 -496,508,512,509,675,180,89,182,838,208,392,771,177,934,88,513,61,943,903,666 -311,509,478,439,890,692,682,361,914,802,720,600,675,576,664,224,522,252,898,650 -384,587,250,396,715,840,595,679,900,135,141,438,844,122,310,566,850,291,205,676 -414,810,370,856,785,628,172,781,88,450,675,339,308,210,832,660,595,77,475,438 -648,77,650,473,817,977,819,524,846,751,323,823,104,67,112,451,394,627,725,578 -620,327,676,194,664,51,140,368,782,528,111,280,145,73,582,486,821,530,372,764 -370,364,79,252,718,204,370,835,825,904,698,312,137,586,387,360,713,229,725,318 -192,776,258,495,644,836,759,139,147,702,658,779,615,816,478,812,657,712,362,839 -386,530,409,863,110,290,938,75,406,457,190,513,368,133,203,753,514,825,644,687 -615,862,808,721,579,671,807,228,848,307,760,74,451,509,484,403,216,710,892,667 -494,763,935,569,778,396,362,723,113,495,897,486,735,495,288,715,937,590,575,687 -478,108,831,687,817,753,687,528,321,201,574,572,444,897,489,568,876,512,508,288 -829,312,350,843,478,252,584,361,625,307,929,570,514,72,219,825,686,570,655,667 -172,910,658,834,657,182,941,182,246,907,373,147,271,183,77,785,429,320,847,726 -855,523,364,690,564,979,145,892,354,525,326,510,723,856,560,445,620,813,525,618 -748,916,783,872,646,676,596,691,316,373,512,915,512,724,831,723,842,324,908,899 -88,766,253,446,940,533,398,506,751,912,18,130,134,477,855,59,516,395,384,76 -795,638,507,766,947,400,474,505,864,612,653,212,529,378,255,911,358,83,51,491 -765,827,584,196,941,390,402,713,901,82,659,623,345,177,309,191,198,223,863,937 -517,635,510,64,415,765,901,365,723,574,623,850,191,917,943,643,413,523,757,830 -218,854,225,812,523,170,593,357,761,291,621,914,584,60,64,198,65,501,848,939 -83,683,222,750,135,847,864,325,80,668,717,630,757,427,137,430,176,777,809,670 -285,570,846,471,759,572,627,721,753,68,414,920,521,677,517,713,901,475,569,67 -135,319,70,328,495,618,78,479,414,782,107,64,489,378,227,444,861,314,441,179 -766,557,983,577,443,573,225,74,259,680,659,932,916,452,560,763,374,214,446,644 -54,509,310,204,580,484,889,371,935,619,520,188,622,653,491,229,66,926,828,688 -560,311,146,911,907,864,696,386,328,776,393,387,947,364,212,688,677,446,361,64 -79,259,476,926,67,375,59,397,750,909,652,947,568,786,208,107,200,830,527,173 -88,836,587,134,901,176,896,287,68,574,903,562,82,877,75,651,561,813,569,209 -480,566,575,639,198,80,935,142,446,948,784,360,716,835,318,171,536,112,843,835 -519,711,796,581,590,382,317,514,389,488,410,663,840,578,450,906,947,841,507,663 -87,569,890,497,368,361,58,413,145,592,144,221,292,445,72,941,791,60,218,814 -389,810,597,156,190,186,507,725,638,349,86,405,644,947,254,201,391,573,758,826 -500,829,643,858,193,191,485,584,370,940,841,820,832,327,565,389,816,677,819,485 -81,499,388,812,201,848,823,288,715,650,868,307,322,53,780,360,650,491,711,896 -816,443,408,197,316,936,487,792,350,492,287,717,350,201,444,111,579,73,409,289 -509,369,890,671,529,444,428,783,170,139,889,649,905,511,508,410,380,399,203,310 -808,711,711,500,512,227,85,810,940,604,786,74,667,684,400,174,480,224,522,88 -105,897,172,780,432,722,287,529,824,524,52,250,136,219,223,249,384,938,559,856 -827,618,152,625,143,933,529,254,400,257,780,144,182,599,576,376,113,199,353,624 -515,253,651,450,659,382,814,254,522,535,906,180,350,358,725,441,135,591,921,54 -290,354,895,627,399,945,355,311,385,496,756,986,893,80,52,308,414,313,572,599 -211,363,501,189,635,891,131,623,493,109,854,572,190,246,206,562,808,365,889,250 -63,792,659,400,946,835,724,641,566,180,824,892,199,528,175,563,687,571,314,557 \ No newline at end of file diff --git a/2020/day-16.ts b/2020/day-16.ts deleted file mode 100644 index baa6ff6..0000000 --- a/2020/day-16.ts +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -import { between } from '../utils'; - -type Rule = { min: number, max: number }; -type Field = { name: string, rules: Rule[] }; -type State = 'Rules'|'MyTicket'|'NearbyTickets'; -type Ticket = number[]; - -const FIELD_RE = /^([a-z ]+): (.*)$/; -const RULE_RE = /(\d+)-(\d+)( or)?/g; - -function applies(rule: Rule, value: number): boolean { - return between(value, rule.min, rule.max); -} - -function matchingFields(fields: Field[], value: number): Field[] { - const result = []; - for (const field of fields) { - for (const rule of field.rules) { - if (applies(rule, value)) { - result.push(field); - break; - } - } - } - return result; -} - -function findInvalidValues(fields: Field[], ticket: Ticket): number[] { - let result: number[] = []; - for (const value of ticket) { - if (matchingFields(fields, value).length === 0) { - result.push(value); - } - } - - return result; -} - -function assignFieldOrder(fields: Field[], validTickets: Ticket[]): Field[] { - // Start out with all fields possible for each position - const possibleFields: Field[][] = fields.map(field => ([...fields])); - - // Process the tickets, and restrict the possible fields - for (const ticket of validTickets) { - for (let i = 0; i < ticket.length; i++) { - possibleFields[i] = matchingFields(possibleFields[i], ticket[i]); - } - } - - // We now should have (at least) one of the possible fields set to a single value. - // Find that, remove the field from the other possible fields, and repeat. - // XXX: We may still have to recurse/backtrack here, if there are multiple combinations. But - // this will be cheaper already because we know what is at most possible. - let pending = fields.length; - const result: Field[] = new Array(fields.length); - - while (pending > 0) { - const knownFieldIndex = possibleFields.findIndex(possible => possible.length === 1); - if (knownFieldIndex === -1) { - throw new Error(`No next obvious field, still ${pending} to find`); - } - // Assign - const knownField = possibleFields[knownFieldIndex][0]; - result[knownFieldIndex] = knownField; - - // Remove everywhere - for (let i = 0; i < possibleFields.length; i++) { - possibleFields[i] = possibleFields[i].filter(({ name }) => name !== knownField.name); - } - - // Next! - pending--; - } - return result; -} - -function processInput(input: string) { - const rl = createInterface(createReadStream(input)); - - let state: State = 'Rules'; - - const fields: Field[] = []; - let myTicket: Ticket; - const nearbyTickets: Ticket[] = []; - - rl.on('line', line => { - if (line === 'your ticket:') { - state = 'MyTicket'; - } else if (line === 'nearby tickets:') { - state = 'NearbyTickets'; - } else if (state === 'Rules' && line !== '') { - const [, name, rulesText] = FIELD_RE.exec(line)!; - - const rules: Rule[] = []; - let ruleMatch = null; - while ((ruleMatch = RULE_RE.exec(rulesText)) !== null) { - rules.push({ min: Number(ruleMatch[1]), max: Number(ruleMatch[2]) }); - } - fields.push({ name, rules }); - } else if (state === 'MyTicket' && line !== '') { - myTicket = line.split(/,/).map(v => parseInt(v)); - } else if (state === 'NearbyTickets') { - const ticket = line.split(/,/).map(v => parseInt(v)); - nearbyTickets.push(ticket); - } - }); - rl.on('close', () => { - console.log(`Results for ${input}:`); - let errorRate = 0; - const validTickets: Ticket[] = []; - for (const nearbyTicket of nearbyTickets) { - const invalidValues = findInvalidValues(fields, nearbyTicket); - if (invalidValues.length > 0) { - errorRate += invalidValues.reduce((s, v) => s + v, 0); - } else { - validTickets.push(nearbyTicket); - } - } - console.log(`Error rate is ${errorRate}`); - - const orderedFields: Field[] = assignFieldOrder(fields, validTickets); - const checksum = myTicket.reduce((r, v, i) => { - const field = orderedFields[i]; - if (field.name.startsWith('departure')) { - return r * v; - } else { - return r; - } - }, 1); - console.log(`Checksum is ${checksum}`); - }); -} - -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example.input`); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}.input`); diff --git a/2020/day-2.input b/2020/day-2.input deleted file mode 100644 index f629519..0000000 --- a/2020/day-2.input +++ /dev/null @@ -1,1000 +0,0 @@ -15-16 m: mhmjmzrmmlmmmmmm -5-6 d: dcdddhzld -3-4 s: vqssdcbl -3-6 b: bbhbbbqbbb -10-11 q: cqqntqhqwwh -4-7 g: ggkgggw -4-7 f: fdfffflfvn -11-16 h: thhrhrwhbshshsdhhhhr -7-12 n: nnnnnnvnnnnn -4-5 f: ffxfhldh -9-17 m: mmmmmmmmjmmmmmmmw -2-5 h: hqrfzhhh -4-7 x: vxxfxxjxwvnlx -11-13 h: dhhhhhhhdhhhrh -4-8 q: qqphvphfrlqqkztgslzb -3-15 x: htblqcbdxdzgvhszxz -4-5 j: jjhnn -3-6 l: bwkjllgcjrzhr -5-8 s: ssmsspsss -1-15 d: ddhmhmvlkppkbbdxbc -7-8 l: ltllllllhgzlv -1-15 m: mtmmmvmmbmmfmmkmmmm -1-3 x: xrxzcxcx -5-6 t: tttttdtv -2-5 x: xxxxs -5-7 l: gclqlml -5-10 g: gggggggggn -6-9 j: xwjjfngjgjsjsr -2-7 b: hbqtchkcmblppvqp -16-17 j: jjjjjjjjjjjjjjmjjj -1-5 p: wpppdlpphppp -3-7 q: mspqqqqq -1-4 k: hkjk -3-6 l: llbllldzf -11-14 x: xxnxvxxxxlxxxkv -4-7 k: zkkksmjmrzxftx -2-4 l: lllwq -7-11 q: tbqqmmvkrsz -3-4 f: gwfs -3-5 z: ztszz -2-4 k: kkpzl -1-2 k: kkwckkzwskgbdc -5-7 x: mxxxdxf -1-3 p: pppp -6-8 c: rcqrmcqmpcc -5-6 s: srgvwsc -5-6 w: wwwwwww -2-6 w: xwwzfwr -1-8 z: djzzzcmz -10-14 b: dbwbbbbbldtbbbrbbq -5-15 v: wvzftvfvzkcvjdvvzcj -4-5 j: lrjdmjj -1-15 q: qqqqqqqqqqqqqqkqqq -1-2 w: vwkw -2-4 c: lccsfmkrnrldzbrc -5-14 r: rcpghlsspmvwvzmpvl -7-9 n: nnnnnnnnx -2-19 w: wwwwwwwwwwwwwwwhwbww -6-7 r: rrrrrzc -3-15 w: mnxmfqgklqddfww -9-13 s: tsslqtsszsqsssqssss -5-6 j: jjjtjrb -8-9 f: fffffffwfff -5-7 n: nnnnnnhn -8-17 d: dnfdqvwngbddvbndbsf -13-14 v: vvvvvvvvtvvvvt -2-3 h: hsbnhhhs -2-4 g: ggcgm -2-7 r: rvrrrrrvr -6-9 n: qpxchngsbhxrgqdgbqs -4-8 k: kkkkkkkkd -1-6 v: mrvlldzv -7-10 w: vvwkwrbnwczwww -10-14 k: kkkknkkkkpkkkdmkh -9-10 s: qqbwmssnssjs -5-6 z: bzvdjz -6-13 j: jjjjrzbrjzjmjzjsk -1-6 k: kkkkkrsskk -8-10 v: vvvvvvwvvzvb -10-12 m: mmmmmmmmmdmm -9-10 k: kkkkkkkkjkk -2-8 b: pbcsbbprc -6-7 x: xxxxnpxxxk -3-7 l: llllllml -4-10 j: jrjzjjjcjx -4-5 g: gggmgg -14-15 n: nnnndnnxnnnnntnn -4-6 h: hzqpgbhwh -4-6 b: plzbkbrpscqbxl -5-13 m: hptczmkkmplmw -7-8 r: vjhrhrkdrrrk -3-4 q: qqqq -11-13 s: sssnssssssmsss -11-13 x: xxbhkwvvxgxjh -1-2 f: ftlrdz -1-3 d: mdslnl -2-10 r: xrzbqcxlvtlrsznplk -8-10 w: wwwwmwwtww -2-10 r: zbzplcvnvrr -5-16 c: lcccccclcccgcccccc -3-7 w: wwpwwbww -1-4 s: svsss -6-8 j: jjllkwnjjjgcjpg -3-5 c: cccbb -1-14 j: jpkjjqjjgqmzbjjhjljj -4-9 w: dwwlwwdmkww -7-8 p: pppppppjhqp -1-14 d: djmfmdddkhfqdzfdddd -2-3 r: zrbjhpg -3-4 j: jjkj -3-4 q: qqqq -1-5 k: kkkkwk -6-13 t: ttzxtjtdjtmtttmtt -1-3 x: jxvx -11-12 f: fffffffffffkffffffff -4-5 l: lllhlm -8-10 n: hnnnnnkdfrnntdhnk -1-2 x: gxxx -8-12 w: pwwwwwwfwwww -1-19 p: ppnxfswpxfpbfcpnnpq -10-11 h: hhhphhhhhhgv -1-10 c: dccbvcccccc -7-12 v: vvvvvvrvdvvvvvvvvvvl -2-11 b: jbncfdbbbbcb -3-4 n: nnrn -3-12 s: btnfjtszszssdrsd -3-7 b: bznkfbb -5-6 r: rhprrhrrrhnzjhr -6-18 n: xznnnwwmwnvfnfnlhn -6-11 v: smsvpcjvvgvtvkmvv -12-14 s: sssssssssssssc -5-6 t: ttttfx -7-9 p: pppppnvppp -4-11 s: fbvfqsswshlgr -10-11 n: thnnnnvnnnnnvbnn -2-13 r: dqnvjskcqhmrrtn -10-11 k: kvhkskkfrkr -7-8 s: sssssssm -5-6 d: fddddvv -16-17 q: qqmkfqvvqdqqckqrw -7-13 d: lddrdgdddzddz -14-17 v: vvvvvvvvvqrvvvvvbnqx -1-4 c: ccqn -14-15 t: tbtrrqgtldttmktrt -8-14 c: csccctccrrcwcqc -1-4 n: nnnbnnn -11-14 p: pppppppppppppppppp -4-6 d: hcrkddqddm -1-2 b: xbbbb -2-7 f: cfwqnzbtfnt -7-11 q: qqqqkwqqlqqqq -2-7 g: gtgsgwg -3-4 w: wwks -2-6 j: rjjstgwskhwc -8-15 w: wwwwsgrwwhwjvgqw -5-6 f: ffffhr -1-4 n: kxcn -13-14 k: kkkrkzkkkkkrkhq -2-4 d: fdtpdlbp -4-5 g: ggggg -5-8 x: skzrxxsxxhknxzxxxpnf -4-7 h: ddhhbxnlhfb -4-15 q: wqqlqqqrgqqqwqqqqqq -2-3 j: jjwlnjb -7-13 k: kkxkknjkkkkkksk -3-6 g: ggmgggggggg -3-4 b: bbgbbfd -5-7 j: jjjjwjjj -4-5 x: hvnhxhxxkzxzxc -2-8 r: rlrrwrrrc -11-14 c: ccgccrcccccbhccccm -1-5 f: vfffffffffff -16-17 f: fffffffffffffffff -5-8 n: nwnnngppnn -10-12 m: mmmmmmmmmvmmm -7-9 l: llllllgll -12-16 v: vvvvvvvvvvvlvvvvv -10-12 w: wwwwwxvwwjwwdwwwq -2-8 x: cxjlkdwctx -10-11 d: mdddlndmsdd -1-3 h: bhkfwhjls -6-9 c: cccpcncccc -1-4 c: tzxzctxhpt -10-13 m: mmmsmwmmmsmmcmh -8-9 k: kkkdkkkrb -3-5 x: xkxjxx -6-7 q: cqmxqqqlhtqpgqsqwqqd -5-7 g: ggzggggqg -2-4 n: ncnvzvrk -6-7 k: kkkkkzk -3-7 n: nnnjcmpgtgxqdwjz -3-6 m: zzzvmmmmlmq -1-4 q: nqqqqq -4-5 n: cnnzvn -4-8 s: bscfsnss -8-9 b: pqbtmxfbt -4-13 h: shqjphgfvkrrj -3-8 n: cnphjnhbtndtcn -11-12 f: ffkfzfffbftfffff -6-8 p: ppwppxspppbp -4-5 d: ddddnddd -4-8 n: qnbhwnzxd -3-8 r: csflkrvrq -7-9 z: zzwtzzmzzzzzxdb -4-7 f: wgfffkw -3-6 d: wgmxddvdwtdtknvsz -6-17 w: mzmwwwwzkxwwcvpwrs -1-8 b: bbnltzsmbbfp -2-5 z: tpztzz -6-10 w: rwtwrvwpwwwwpx -11-15 s: sdsssssdsxlpsss -12-14 s: sssvsssssssssr -10-11 x: dqxfvxxxxlx -6-7 z: zqzzzlzz -1-2 t: ftvbp -10-15 d: dddddddddmwdddshdd -8-16 w: wwwfbwwfqwzwvwthjw -6-7 x: xxxxxxpx -11-13 h: hchhhhhhmhfhp -8-11 m: vmmmkmmmxvmmmt -12-18 w: jwmpwwwdwwwwkwswdwz -4-9 f: hwfftvxmpfffff -1-5 n: nhchnnkpn -2-16 l: nlxtpcdlzdkhnmqsvqfg -4-5 r: rrrrr -14-16 d: dddddpgdrddddcdbddd -4-5 j: gskjzxjjz -13-15 s: qsmccrpnsrrvwsk -16-17 f: ffffffflfffffffff -14-15 l: nllcllllvnlwltll -3-4 g: gxghgggdggg -5-10 x: xfxxqljxxkxxx -1-4 q: lmzzq -13-17 x: xxxxxxxxxxxxxxxxt -8-12 b: bbbmxbbbjbbbb -14-19 x: glxxxxhxxxxwxjxxxxc -6-19 d: ndflnddcxksdzdbwdddt -3-9 c: ccccccccl -2-17 z: zrxzbzwzzzzzfzzcz -1-4 m: fmmmml -9-17 l: lllllllllllllbllllll -7-10 r: wgrnrkxrrmrprxrr -2-3 f: vcfff -12-15 t: tttttttttttwtttt -1-7 c: xcccccc -1-9 t: kftttbttchttttttttt -1-4 c: cpkcwmdwxnwvjzfbj -12-16 n: nnnnnnnnlnnnnnnnn -3-4 q: qcjq -4-6 t: tdttkshpmlgqstpttfcc -3-4 j: jjmcxlb -3-19 w: qwdwwhwwjqmwwwwgqwfw -7-12 z: zzgzzzwzkzzb -14-15 c: nccccbdqwdccccd -2-4 k: kkkkrv -14-15 k: kkkkkkkkkkkkkkrkkkk -3-14 s: sspsssssssssstsssss -2-6 r: tdrrrwcrrcrr -1-2 g: gfgg -4-7 z: zczhzkzzccmpg -3-8 t: ttvtscttzcxtt -3-7 q: svkxfrxrvqqpmxzsbk -17-18 p: ppnppppppppppppppb -15-16 b: brbbbbbbbbbbbbpbb -2-4 x: shxx -6-15 m: mmmmmmmmmmmmmmvm -3-4 b: bbbbb -8-10 k: kgkmkkkjkkgkkmk -9-12 j: jtjlwjjjjjml -3-4 w: whwdpqfwghhj -12-13 s: ssssssssssssg -13-19 n: nwdnntnnnqnnqnrbmnmn -14-18 z: zzzzzzzzzzhzzzzzzl -4-11 b: bbbbbbbbbbhbbb -3-19 x: jwxjftcjnkmlgcfgxzmj -6-11 x: xxxxxxxzxmxx -2-4 g: vqgg -5-6 b: bbtbbvhpvbbm -7-9 t: csthttrtttt -10-13 q: qqqqnqgcqnqqqlqcq -8-10 j: jjjjjjjdjw -9-10 v: vrpnvvvvsvqvcvv -2-12 q: jqqqqqwqqqkqkqqq -4-12 z: zrcznzmzzwzzfs -3-6 n: ntnptpnvnns -5-10 d: ddddhddqdd -1-4 l: pcdsl -4-5 d: ddddz -3-10 v: kgnvtcvfvvqkvgwkvj -16-17 x: pdpxctpsxgpjshbxvvq -2-11 k: kkkskkkkkkz -1-4 d: ddddm -3-4 b: bbqm -4-7 b: bbrbbbb -18-19 h: hhhhhhhhhhhhhhhhbhwh -8-10 p: pvlxpppbppppptqbwgp -1-3 w: sfwgwnvghzrn -3-4 l: llwlln -15-19 j: jjjjjjjjjjjjjjbjjjjj -1-7 d: ddddndddd -6-14 c: ccccchcdcccccc -12-17 f: ffxffjffhffzsffffffv -5-9 b: pnbglbbbrdn -8-9 v: vvvvvvfwvvqgc -5-10 l: llklllgllzlm -2-5 t: tttttt -3-7 f: fsfhzcfffvffnrfv -2-5 q: gqqqq -6-7 c: ccccccj -9-13 g: vrgjgkggvpggggggg -4-10 n: nrqnnknbvntszznzmgbn -2-7 x: wslrxrx -4-6 s: ssszbwst -4-6 m: mzmcgnm -6-8 g: gdggggggg -3-6 q: qqqqqknrq -16-17 d: dddddddddddddddzd -4-11 b: bbbpbbbbbbvb -3-4 p: jrppp -2-7 n: wgznngfndc -2-9 f: kcfrnfcpknxfgj -11-14 l: nvdlmzgpllqzllvlqlt -5-6 g: ggggdsgg -15-17 r: kqflshskjhrcgrfcr -13-17 f: gpfwfffffffbfffffff -15-17 s: srssfssshssgsstss -4-8 f: fvfpfbffffb -11-16 w: wwwwwwwwwwwwwwwr -3-4 j: jhjvhwd -4-5 r: rrqtrr -6-14 w: dkwwqwdrxrwwbxwqgww -4-5 s: sssgk -2-4 d: ddtmxd -8-9 w: wwwwwwwwn -2-15 d: rhkgdbbzdszjmbm -2-7 h: jvqmhwbhfqkgzw -6-12 q: qtqqqfqqqqqd -3-5 g: gsxcggzfwgggsl -2-7 p: dprmlmpwpw -9-10 m: mmmmmmmmmkmm -1-4 z: zzzqkfzt -2-8 l: llgllllb -3-12 w: hwwcspbckppcgwb -2-3 s: tnsxtstsstb -1-2 m: fmsm -6-10 q: qnqfqqqqqv -5-10 x: tlgxxwcxgx -8-16 k: kmkknmkgkkkkbkkkkkr -4-16 b: nwbbfcfngbbspnxbj -2-9 m: mmmnmvmvjxmmdmr -5-7 k: fkkkjfbwfkk -2-4 m: tmkfjfqqjmgsjmtz -3-15 z: zzzzzzzzzzzqzzwzzzd -9-10 n: dnnnnnxtnnnnnn -2-3 w: wwwlcwzl -9-10 j: mzbjvzjjvjjgrjj -3-4 d: dhdd -2-6 r: jrcrwjr -9-10 v: bkvvvvvvvjvv -2-6 x: xnwnnx -18-19 k: kkkkkkkkkkkkkkkkkpk -3-5 j: gtjrr -5-6 j: jjjjjj -5-6 k: kkzknk -12-15 t: tttttttttbdlvtq -1-4 d: ddwvz -3-8 f: xlfffrpf -1-2 z: zzdscgwbxtxrd -5-14 n: nsnnnlnnznnxsnnnnnd -9-10 g: gwslkgdgwqdbgws -4-6 f: sfcgkffmfc -10-14 m: dmmwlqmmmmmmmmnm -8-12 n: nnnnnnnnvnnv -15-16 l: lllllllllllllvqlf -1-10 t: tftpttjtnt -2-7 t: ljzdkxtwvbmjtff -2-9 w: stwwlqcbtws -4-6 h: hjwhhvvtpg -3-5 v: vvgvv -8-12 d: ddhcdpdjdddhddmr -10-11 x: kxxllzjrdxlsxx -5-6 f: fffjfrff -17-18 b: bbbbbbbbbbbbhbbbbbbb -3-8 r: znrntdqtmrg -6-12 s: srsvsmsssssssssssss -2-13 z: dzfvpthfxnpnz -7-13 j: jjjjjjrjjcjjw -9-10 l: tllllllljl -12-14 m: mmmmmmmmmmmmmm -17-18 l: llllllllqlllllllggl -1-9 d: dkmqddddzdnrfckdz -6-7 m: gmmmmmlh -13-15 t: ttttxtttttttggbt -6-7 j: jmzvwkjjnjsnjkjxj -1-17 m: gmmnmdvfmmtmmqmmzcj -3-5 l: hvxsjt -7-8 x: kxqczpdxfpjp -2-5 k: kgkkhkdkk -5-7 v: nbjvcgsvf -8-9 d: cxddddnsxd -2-3 p: mmqnjbtbpnmp -11-12 m: jmmmmwvmmhtmmmmlmm -3-14 m: zmmjsqfmqrnzmlmwrjm -3-6 n: vnnnnjn -11-12 j: jjjjjjjcjjjs -13-17 r: rrrrrrrrrrrrrrrrrr -4-5 c: bcncn -2-3 j: bjftxcnzpnjrzxhxlp -9-12 z: tzrlxlzdxzsz -3-5 j: sjtltj -5-7 w: wwwwwww -5-7 p: ppzppcwkvwmwpscfpp -9-10 j: jcjjjjjjjj -3-4 m: mmrm -1-10 k: zkkktkkkkk -5-13 d: bpfldtnfrbdfk -2-3 s: zsskw -6-12 x: xxxxxkxxbxjxlzx -3-9 t: ntgdtbtwnntjbcsfz -6-10 j: sndjqjjdjbfjc -3-4 t: ckqtjtffctwtcp -2-3 v: wvhffpnngzv -7-8 r: tlrncrsg -7-10 g: gjggkfvffg -4-9 x: xpxlxxxmpr -6-9 r: srrrprrrr -7-10 v: gvvnnvhvvvvvdjjvv -4-6 s: psnsgsnfxlscwss -2-4 w: vwwpwx -2-4 b: bbbb -2-16 v: vvvvvvvvvmdvvvvv -3-5 f: ffkffjffff -6-9 q: lqqqqjqqxn -1-5 w: qcvwwwhw -2-10 w: wwwwwwwkjz -6-8 t: tttttttz -13-14 x: xxdxxxhbxxxgcdx -2-4 n: svkl -8-14 f: fffffcfffffffnffw -3-6 n: lsnnnpnnn -11-13 l: lllllllblllll -4-5 s: sssss -3-4 z: zbzt -1-4 x: xxxsx -8-9 c: wlxctcccrqccsccr -5-8 v: vvnvndfqq -4-6 r: rrrtrc -10-15 b: nbbbpfbbbcbzzxbf -4-5 s: sglpschlsgsqbskrd -13-17 k: bvfzktkkkzkkjkkwkf -1-11 x: zkxxxgxxkwxvxgx -15-16 d: dddddddddddddgdwd -2-3 p: pzpprsp -16-19 s: sssbssscjsshwmmszst -11-13 s: stsssssssgmssp -10-11 s: sssssssssgs -5-8 j: jjjjttkj -9-12 s: ssssgsssswsv -16-17 k: kkkkkkkkkkkkkkkwb -9-10 g: bzcdgvrvqg -4-5 n: nnnrn -4-12 n: knnrnnxnnnnjndwn -1-3 m: mtmspm -16-17 b: bbbbbbbbbbbbbbbxb -9-14 m: mmdmqwwbmmlxmjljmm -6-11 z: wzzzzzzzzzzzzszxzvz -2-8 q: qqqqrqqqq -3-4 f: ffhf -9-12 t: ttlqqthvttcttttm -5-8 w: zwwwwlmwwlww -5-7 z: zjjwzkkkjlwzvkp -7-10 z: zkzgzzzxtzz -12-13 v: vvmvvklvvvvgv -10-14 t: ttttttqttttsrttktv -7-10 l: llhlllzllv -1-4 j: blwjjmj -8-10 k: qpffpqskqk -5-9 w: wkdjxcwwswwwwwh -11-13 b: bbbbbbbbbbgtjb -14-16 c: ccccfcbccccccccccc -9-11 l: lflnpwbcmld -8-11 q: qqqqqqflqhtpqq -12-18 z: zzzzzzzzzzzmzzzzzl -4-5 x: xxfhxx -6-16 z: tfrhztxxzzqczznwzz -4-13 l: vlrlmlllldllq -14-15 b: bbwbvbbhbbbbkvnbbbb -3-5 x: frxxx -11-13 f: ffbfffnfffjlffffff -5-6 d: dkrdrgdd -6-8 g: gggwglggvtkglg -1-5 s: sqsnpp -2-4 b: bxjnb -1-2 h: hhfr -10-19 b: tzbpbsbbbtbbbbbbbbbb -3-4 p: pkmcpm -1-8 q: qqqqtqcnqxkqb -13-15 s: ssmssqssssssssts -4-6 q: qqdsqrqq -9-13 z: zzbzzzzpzzzzz -19-20 r: xlrrrgrrrcrktrrhrrrc -9-14 q: qzsrqqqjxwqqhqd -7-15 g: ggggggsggggggggp -4-5 w: wwwkq -7-15 h: ghgpkphhzpmhjpwxq -15-17 v: vcvvvdvvvvvvvpvvhv -1-2 j: qjqbfwbj -3-9 c: nvcwkcndt -14-15 c: cccccccccpccgkclcc -5-6 p: pppppp -12-14 h: hxtxhthhshkrmh -1-2 q: wqjqzqqk -14-15 f: fffffffffffffbqf -7-8 j: vjjjjjfh -7-12 p: trzzppxpptpfp -13-18 w: wwwwwwwmrwwwwwwkwwww -10-11 f: rfffszjfsvn -9-17 l: llllllmlllllllllkl -5-12 s: xssssqssshsss -2-6 x: fxxxsxbnx -4-6 n: nnnnxhnn -10-11 g: gggggggggqg -8-16 n: nknsfcnnnqgnnnxsnfnj -4-7 n: ndnnnnnn -8-9 q: shqphcskmqjqvqqqq -9-10 r: rrrrrjrrrrrr -16-18 z: zfzzzrzzzzzzzzzzzhzz -2-13 g: gkgggqggggggrgg -12-18 v: vvvvvvvvvvvvvvvvvvv -3-4 s: hssq -6-11 h: kdwftsxqcnhph -16-17 t: ttttttttttttttttt -6-11 f: fffffdffffsfffffffff -10-14 p: pppppjvpppppph -10-15 b: bbpbbbbbbtbbbbb -3-7 n: nnnnnnx -3-5 r: rrffrsr -10-13 r: brrrrrrrxrrrrr -6-7 f: ffffkjf -3-7 r: srdrrsrrfrcr -4-9 b: gflbcxtvknsbpjbwrk -8-10 p: pttpkfppcppdznpgpp -13-16 q: qqqqqqqqqqqqqqtqs -1-4 r: rrrwr -1-2 g: zggggggggggg -7-8 j: jjjjjjwb -18-20 t: pwnrvbdzxntvgjjjltqn -8-13 f: fffxffflffffff -4-5 k: cklkk -10-11 m: mmnmmmmmmnm -11-16 q: qqqqqqsqqfsqzqqqq -2-9 n: nnnnnnbnnc -7-11 d: sddnmgfkdddzdd -1-4 f: qfdlftk -8-10 p: pzpppxphphpp -2-4 m: mlwf -6-8 h: jxhhhfztzh -5-8 s: ssnnnssssstsssssd -3-5 x: hlxsx -7-8 h: qhhhhhhwdhph -2-7 v: gxdvcvw -14-15 n: nnnnnkhnfnnnfnnnnnn -9-10 l: lllllllhlnklx -13-18 j: jjjdjcljjjjjjjjjjhj -1-7 h: jkhhhhhhj -9-19 z: tzznzzztcbxkzvssrzzz -12-18 s: sswssscsstnssjssss -4-9 z: zzzxmzgkzspdmq -6-13 d: ndldddpddddddkmdd -8-9 q: zgqrkhxqq -3-6 m: mmmgfdw -1-3 l: dlls -10-11 b: kbbbsbbdbkbqbbbbs -2-4 b: bbbp -5-6 c: xctccckq -3-5 k: kkkkk -12-14 b: bbbbbbzbbnqbbb -6-8 q: jmmhqqlqqkgqcjvqq -11-12 g: ggggpggggghsgg -8-9 h: hhhhchhhbh -10-11 w: zwwcfgwwwwc -5-8 x: xxxxnxlxxx -1-4 f: fffhf -2-3 f: fbwfxr -5-6 f: vrfffd -14-15 r: lrrrrrrrrrrrrfc -7-8 t: tbnptvtt -16-19 r: rrgrrrrrrrrljrrrrrrr -2-4 b: bbpsh -7-13 m: gmmsmmlmmbmmmmmmmgkx -16-17 g: ggggggggggggggrfgg -1-2 g: fcfmr -5-7 l: lclllll -3-5 n: nnnccgvn -1-4 v: npvv -5-11 s: sshsxsswshss -9-12 x: mxxkxxxxsxpkxsxhnktx -3-4 f: fsff -5-11 b: bqzzbcbbbxbk -3-7 s: ssxsssv -6-14 p: pxppjppppppvjp -2-4 h: hhkch -5-7 s: sdshspsssqs -2-8 k: vwkkkkwkskjr -17-18 m: mmmmmmmmmmmrmmmmzm -12-15 w: nwrgwwwjpwwwwpv -3-4 t: ttft -5-11 f: kfffzffzfffk -15-16 d: ddhddddddddcddddd -3-10 l: wplpvlrcqwlblvlcqm -2-5 z: zpzzz -3-5 v: vvgvv -3-4 b: jbgbb -14-15 d: ddddddndddddddd -4-13 z: zszfktzrzjtzzbmn -1-8 b: xbbxrbbbbbb -3-4 t: tttftt -5-9 v: ptvvvcvvvvvnvvvv -1-2 n: tcnnnnln -5-6 h: hhhhhh -10-11 j: jvjjhfjbxjj -4-7 t: twtdttttttttt -12-16 z: zzzzzzzzzwzzzwzzzzzz -7-18 l: hnhcvlnxglxlldlfgvll -2-5 j: jjjjjj -2-8 n: nrknnntn -8-9 z: zzzzzzzqz -4-5 z: zzzzr -1-9 t: bztttgtllwq -8-12 n: ckjnntmkxxcnwkqznp -2-4 b: xbrvvhbbb -1-4 d: dddzqd -13-17 w: wwlwvlwpwwdwwwwqb -3-5 q: lqzmlq -8-9 z: bpzzzczzpzz -1-6 n: nbjqmnhxwh -6-8 q: qqqqqqqzq -16-18 r: rrrrrvrrrrnrrrrrrb -3-8 l: lbfdwlpzmkl -2-3 g: srwcwmgvzjjxj -8-17 w: wwwwwwwjwwwwwwwwww -19-20 t: tttttttttdttttttttvf -1-11 x: pwnwxxfxnkxxtzpglx -6-7 g: lgpglng -5-7 l: llllfll -5-6 p: ppppppp -3-4 x: xxdf -4-15 l: fgkzwrrpmvmhzplsqp -2-4 b: bbqjb -4-6 k: kbkkkwkkk -4-8 p: mppzpprpp -14-17 n: ttfvdtwxnnfdsnxbn -3-5 m: mmzmmm -6-7 k: kkkkndk -1-6 r: hkkrln -4-6 h: hhhhhmhhhhhhh -7-10 k: kkkkkkkkksk -3-4 g: fggggg -5-12 x: qhgrxxhrxjjxxhxgb -3-5 x: lxpxxb -4-7 f: frffsfjff -4-6 d: dpddjfxdrt -11-13 f: fffpxfcfffdfnfzf -12-18 r: rrrrwrrrrrwrrrcfrcr -18-19 q: kqqqqqqqqqqqqnqqqkqq -3-4 b: bgbrf -15-17 s: ssssssssssssssbdss -6-9 d: bnvlpxlctvdd -1-2 s: smsss -2-9 s: cpgrfdfmm -5-12 j: jjjxdqjctjjtnzcjq -9-16 g: xqzgsrdtcvblfpmg -11-15 q: qqqsqqqqwdqqmqqpqh -3-8 d: xddzddtdnk -5-8 p: blppgpppppppx -7-9 m: mqwlxbbcmqf -6-8 t: ltttbttsbtrtts -12-13 k: kqmfkcvkwsnddkk -16-17 t: hrkwqdtckqdktgctj -2-4 m: mmmm -2-11 l: tlflzkxlvlq -5-6 j: jjjjjl -2-13 x: wzfjxsbqznqlx -4-8 s: mssssfzpsh -7-17 v: vvxvvvllvxvvvhrvvv -3-6 h: qchchw -4-10 n: nllnnbnrvnnnmgnzb -16-17 v: vvvfvvvvvvvvpvvvjv -2-14 f: lpbfwlffxhlxfffkf -5-7 w: cfwkwnl -4-6 n: nnnnnn -10-11 d: dcddddddddd -1-2 d: nvrdpnvnlxccjrd -15-16 v: vvjvvvvvvvvvvvhzv -3-4 l: wwlpllqk -2-4 p: pvpp -2-3 b: bmbf -2-12 m: snpdndwgtfqjlzdmmth -5-8 j: rpjjjjlpsj -5-9 g: gdmvgsgjrhg -6-7 p: pppppdspp -2-9 k: dktlkrkwlnd -9-18 b: bbxbbbbbrbbbzbbbbvb -5-9 t: ttqdcwdjtwtqttttbc -8-10 d: njdddddtddhd -4-12 r: fkrfrrrrrrrgr -6-7 s: ssskgxssbs -2-6 m: mtmmmkmm -11-12 h: hhhhjhhhhhgh -8-9 q: kfqkscqnq -6-12 d: sdpddmvdvdxdl -1-8 f: cffzgfffkfff -4-9 v: vvvvcnljw -4-5 p: wplvpp -2-3 w: kxwwww -3-5 m: nmmmmm -2-6 t: ttntttjhctkztt -11-14 v: vvvvvvvvvvqvvf -7-8 z: zzgjqzzzzzdzzkzw -13-15 k: kkkkkkkkfkkkkkk -6-7 m: mmmmmfmgm -7-8 m: fgxsdqmnmmszv -1-3 p: pqppp -8-12 s: sssxqstsssnfsxss -7-10 q: qqqfqqxqqqq -2-5 x: djhvxxm -3-5 b: bjbbbrjgbbxkbgpqd -3-17 c: ccscccjccmclccccccc -8-12 d: djrdgddwxddxskt -7-9 h: hhhhhhzhmh -4-8 l: jwlplsct -6-10 q: qvqhqxnqqmz -1-5 w: wwpwqw -3-12 d: pltzkcsdhphdmdxkb -1-9 k: kkkkkkkkx -2-6 d: dbddqddd -11-13 n: njnrjnnnnnqzn -2-4 k: kkkkkk -11-14 g: gggggggggggcgngg -15-19 v: vxqvvvvvvvxvvvbvvvdv -9-10 s: ssscsssssf -1-14 m: mmmmfmpqmmmmml -6-8 t: sttqtbtjt -5-7 k: vkkshkw -5-7 x: xscxxxm -6-12 d: pddxdddqkdddzmddpd -2-14 t: gtmxtcttqtttxtv -7-14 r: rrrrrrrrrrrrrpr -15-17 d: ddddfdddddddddddmd -4-5 x: xqxxx -11-13 w: wwwwwwwwwwfww -5-6 j: jjjjjj -5-6 m: mmmmmm -1-3 b: fbblbbgbx -7-8 v: vvvvvxvrvd -6-11 f: ffffpwpfqfhfzxdc -11-17 m: mtmdkbvmjmxmmdmmgb -8-12 h: nhbtsbhjhgdh -7-11 w: wwwpwwdwwwd -11-12 f: hffrfffffffqqf -12-13 f: flfcffffffffqdff -2-3 v: hbbv -8-11 d: drdlbdhwdsddd -6-9 w: swrwnbwmkxwt -10-13 l: llflsllllntlll -8-11 v: xvvvvvtkmcvvvxh -3-4 h: hzhbh -11-12 b: bzbbbbbbbgzxbbbbbm -13-17 l: lqwxqmqmjlsmfwltkzl -1-5 l: mwllx -7-8 c: cccnccxcc -6-12 b: tbbsjbkprrdg -3-5 z: zmpzc -5-8 j: jjjltjjj -6-11 z: xzlzgzqhqwgz -4-5 m: mmmmmm -5-6 q: pqwfqh -9-14 p: pppppptfhpzjtct -6-10 w: wdwwwlwwdww -14-17 m: mmmmmsmmmmqmmwmmm -4-5 v: vvhpfnvv -1-7 q: qfqqbxqvqf -6-11 z: zzzzzzzzzzd -6-13 g: gggggfggggggg -12-13 d: ddpdjqdddddmd -8-10 n: nnndnnnnnn -6-7 z: zzgdzzdvz -6-8 n: vdnvnsnnnlnn -3-4 b: bblbl -1-3 f: zpfjkfr -7-9 h: fhtxkhwhgq -7-9 x: xxdxxxpxx -2-3 v: vmxv -18-19 z: zzzzzzzzzzzzzzzzzhrz -4-6 x: hjlsdv -2-3 x: jzxxvkhsxxck -1-9 s: sfjvsjqvss -8-12 j: xxcmpzjjtmkswwr -4-10 s: ssjtvssslwszss -9-16 h: rhhphhhhwwhhhgrhhh -7-8 h: hvhhhhhzh -7-10 m: mmmdqbtssvmfmmmgr -5-7 h: hhbhzhh -5-10 c: ccccqcwxcccc -4-6 q: bmhqqbpfrqfdkq -7-9 r: rcmrdrrrjlrscrrhkl -3-4 t: ttgz -8-12 g: mgggtggggzgzcphhx -6-8 d: dvddfctd -2-3 g: gmglf -1-2 m: dmqwpbhmmktcvc -6-8 z: bzwzzkxqpz -1-9 x: xxxxbwvxcxxcxwznw -3-6 z: zzzzzz -5-6 k: kkkkhk -12-13 q: zqqnrcqqqplqqndfg -9-12 l: jdvxtbqblmllfbnlff -3-6 v: vvkvvv -4-7 v: xbtzjdvp -8-10 h: hhmhhhhhhnmd -7-8 t: ttktgqfzxrdxqf -4-5 g: gggjf -6-9 q: qqqqmmqqqqq -1-10 w: rwjwwwwwrcw -9-13 b: ssbbbcbbbbbbd -2-3 g: bggggv -6-11 w: wwwwfwwxwwww -5-9 p: ppjppppzt -3-14 z: gpzzzdzzjzzpzzzz -1-7 v: vbbfvjz -2-5 q: qdwczqqq -1-5 r: rrrrhwtf -8-14 d: dddddddtdddddddd -7-8 p: ppppppzlp -5-6 s: lbssnssss -1-8 q: lqnpqqqqq -1-4 k: rkqkkk -1-9 z: zgkxmkmgqzg -1-5 b: cbbbbbf -1-4 c: dctcc -4-5 x: sxxtl -2-8 m: qmfqbfmlkkkjzhqjbxpd -8-16 h: lhlghlcbqgsmjhbh -8-9 x: xxxxxxxxx -10-11 l: cvndhntlghk -8-11 d: dddddddcddz -4-5 j: jvjpjj -1-2 d: bmhdpdr -1-4 j: jnjcjnjtd -4-8 m: djsvzshmxmgb -4-10 k: bhpkgzksrkkqk -4-6 l: lllllwlvwlglxqll -9-10 h: hhhhhhhhhm -3-4 q: qqsbq -7-9 l: dlllllgllllszg -10-12 l: lllllllllvlzl -1-5 k: kkkkr -10-11 w: wdwfkwwwwww -8-10 g: rzswrffrqgdhgzm -3-5 z: zzzzz -8-14 p: pplxppppzprpdpjpppdp -6-11 g: mkghrgcmhxggcpddvx -4-6 b: sjwbqv -1-2 q: qvpqlsqqqrnbp -8-20 w: wwwwwwwwwwwwwwwwwwwg -12-15 m: mmmmlmmmmmfwmmm -1-14 x: xxxxvxsxxxxwcjxvxxx -11-14 g: ggdggggggggggx -2-5 r: xrqtf -10-12 q: qqqvqcqjqjfqqxqqkqj -3-4 c: cvszc -2-7 w: mwwwwwvwx -6-8 r: hrgrckfb -4-8 d: ddddgxcznlnwdddd -1-4 c: drhvzzc -3-14 n: pfnjnnhpnppfnrbhz -3-4 n: bnnnb -13-15 h: hhhhhphhhhhthhgh -3-5 l: lfllpmknmplx -1-12 c: lcchctpccccccx -8-9 l: lznsllwlbllmllzl -7-9 w: wwwwqshnwkwwww -10-12 k: zxkknkxkrkckkr -9-12 r: rdrkbkgrrrrznrr -12-13 g: ggggggvgggggr -2-5 g: vgxggr -5-6 c: cccthsc -2-3 t: nptdqmfglpzdvwkspt -4-13 q: qqsxdqqfngqqkqq -17-19 r: rrrrrrrrrrrrrrrrxrf -7-11 t: ttttmthttttt -1-5 l: lllwl -8-12 x: xxxxxxxbxxxwxxx -10-11 d: dddddbfddddcdd -3-5 f: lfffb -1-4 f: ffff -1-9 s: swdckstss -7-9 p: pbfzppbmp -1-2 p: xpqssm -6-16 h: hlhhqdhhmhhhhhphhrh -4-5 b: pbbgxbhqbzvnwxxb -7-10 n: nrbdnnnwnnnlnn -1-2 r: mspcrbgfqs -12-16 l: rlvmtklhllrvljlllx -7-10 p: mpppppprpmjs -6-7 g: gpggwmggggv -1-4 q: qqdqlqq -9-18 x: xxxxxxxxtxxxxxfxxxx -2-4 h: hhhshh -3-4 q: qllq -5-11 g: ggggggggggsg -1-4 r: mrwbr -4-6 m: knhmnm -13-14 p: pppppppppppppp -9-12 v: vvtvvvvfvztvvvxwqlg -11-13 r: rrrrprrrrrzrr -7-11 z: zzzzzzjzzzzz -17-19 d: ddddddddddddddddjdd -4-5 c: ccncdc -4-6 x: gxxvqx -2-3 g: ggpg -6-11 m: blgvnmbxhpmxmb -2-15 w: wvdwwfqjwqwvmfrzw -3-4 s: ssdw -6-7 l: mmllqlcllklxcml -16-17 l: lllplllllllllllllnl -2-4 h: qtwhwz -5-7 v: xvvwfvfvv -4-10 k: kkkkkkkkqkkk -5-6 f: qzvvpf -4-11 d: whhddttshzds -10-13 q: qjlqqqqqpwqqgqq -11-12 w: nwwwdmvwwwwk -4-8 l: rlljllhljl -7-10 s: sssssssssd -2-8 c: qcgrtxrfccgc -7-8 n: pnnngnnnvnwdnn -8-10 c: cscckctxcrhgc -1-4 n: ngnncrnn -6-12 t: ztzqttbmtztpsnrnt -8-12 b: bbbbbbbbbbbb -1-4 z: czzzzzzz -1-2 k: kktmkf -10-14 x: xxxjsxxnxxxxxqxxpx -11-15 v: vxvvrvvvdvvvvvbv -7-9 s: nsslmtsdxbxfsfssswfx -12-15 l: lllllllllllfcltllll -6-7 q: qqqqtqdqq -15-19 n: nnnnnnnnnnnnnnbnnnn -6-8 s: ssttshsks -16-20 r: rrrrprrrjrlqrrsrrrrb -7-10 q: qqqqqqqqqq -3-4 w: wcbw -5-6 g: tcggrxgrgvl -10-12 l: kllswlmlglps -4-7 v: qkvvvvqxjktkvvvjv -5-13 r: rrrrqrrrrrrrrrr -1-2 n: nnnnmb -1-8 x: xktqbxgkkjwlt -3-4 k: kskk -16-17 k: kkdkkkkkkkkkkkkwk -10-15 n: vnnnnnnnnqjnnknnnr -8-15 m: mfmmgmmqmmmmmkmmmmmm -4-8 k: kkkgkkkjkkk -16-17 h: hhhhhhhhhhhlhhhqh -1-4 p: ppprpppppp -1-9 g: gbdxggmggrgw -1-5 f: vfffff -2-12 d: jzvwdmsqpdnh -12-13 w: wwcwgzwwwwwhwwwwww -9-10 z: zzdzzlzvgzzztzzz -4-5 f: ffftff -8-14 x: xxxxxxxrxxxxxx -1-4 r: kgrrvrrvrr -3-4 w: zkpwxkk -2-5 k: tkckkfcvxkxk -3-9 r: rbrrrrgrrrrkbrrr -3-4 t: ttxx -8-11 z: zzzzzzzzzzz -6-10 p: pnwhxpmxpfskq -1-16 d: dddddddddddddddgdddd -1-7 c: kctcccg -1-5 q: sqqqrqqq -14-16 f: fjfffffqfkfffjffff -3-8 v: knvrrqvtv -1-2 p: ptgswlvpdnmr -3-5 v: vvkmnvdwk -10-14 r: rrrrrrrrrhlrwrrrd -2-11 f: xffffxjfffzfffpf -1-5 p: nppppppp -15-16 x: xxxxxxxxxxxxxxsx -15-16 b: prhbmdvwcmtzpvbb -11-14 t: rngdttnzqtjtcttdvbmt -8-10 f: ffvldffqfqffgf -1-3 r: rzqrmz -7-8 n: tntnnnntn -6-14 s: qpvlfbsgswsnwsmpz -9-12 t: tvwstttttttktwt -4-6 g: vslqbgg -9-16 d: dsdddddddrdddddhdbdd \ No newline at end of file diff --git a/2020/day-2.ts b/2020/day-2.ts deleted file mode 100644 index 8a5ec53..0000000 --- a/2020/day-2.ts +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env node - -import { createInterface } from 'readline'; -import { createReadStream } from 'fs'; - -import { between } from '../utils'; - -const POLICY_RE = /^(\d+)-(\d+) (.)/; - - -function parseOriginalPolicy(policy: string): (password: string) => boolean { - const [, min, max, policyCharacter] = POLICY_RE.exec(policy)!; - - return password => { - const count = Array.from(password).reduce((result, c) => c === policyCharacter ? result + 1 : result, 0); - return between(count, Number(min), Number(max)); - }; -} - -function parseRevisedPolicy(policy: string): (password: string) => boolean { - const [, pos1, pos2, policyCharacter] = POLICY_RE.exec(policy)!; - - return password => { - return (password.length >= Number(pos1) && password[Number(pos1) - 1] === policyCharacter) !== (password.length >= Number(pos2) && password[Number(pos2) - 1] === policyCharacter); - } -} - -let validOriginal = 0; -let validRevised = 0; - -const INPUT_RE = /^([^:]+): (.+)$/ -const rl = createInterface(createReadStream('day-2.input')); -rl.on('line', line => { - const [, policy, password] = INPUT_RE.exec(line)!; - const validateOriginal = parseOriginalPolicy(policy); - if (validateOriginal(password)) { - validOriginal++; - } - const validateRevised = parseRevisedPolicy(policy); - if (validateRevised(password)) { - validRevised++; - } -}); -rl.on('close', () => { - console.log(`Found ${validOriginal} valid passwords according to original policy`); - console.log(`Found ${validRevised} valid passwords according to revised policy`); -}); \ No newline at end of file diff --git a/2020/day-3.input b/2020/day-3.input deleted file mode 100644 index 846977b..0000000 --- a/2020/day-3.input +++ /dev/null @@ -1,323 +0,0 @@ -......#...........#...#........ -.#.....#...##.......#.....##... -......#.#....#................. -..............#.#.......#...... -.....#.#...##...#.#..#..#..#..# -.......##...#..#...........#... -.......#.##.#...#.#.........#.. -..#...##............##......#.# -.......#.......##......##.##.#. -...#...#........#....#........# -#............###.#......#.....# -..#........#....#..#..........# -..#..##....#......#..#......#.. -........#......#......#..#..#.. -..#...#....#..##.......#.#..... -.....#.#......#..#....#.##.#..# -......###.....#..#..........#.. -.#................#.#.......... -.........#..#...#......##...... -##...#....#...#.#...#.##..#.... -...##...#....#.........###..... -.#.#....#.........##........... -....#.#..#..#...........#...... -..#..#.#....#....#...#......... -..........##.....#.##.......... -..#.#....#..##......#.#.....##. -..#...#.##......#..........#... -......#....#..#.....#.....#...# -#.#...##.#.##.........#..#..... -...#.#.#.........#.....#.#.#... -..#.........#...............#.. -#..##.....#.........#....#..... -...#....##..##...........##..#. -......##.................#.#... -##.......#....#.#.#.....#...... -....#.#...#.................##. -#...#.........##.....#......... -#....#.###..#.....##.#....#.... -#..#....#...#....#.#.#......... -.......#...........#....#.....# -#...#.............#........#... -.......#.....#...#..#.........# -.##.....##.....##.......#...... -....##...##.......#..#.#.....#. -.##.........#......#........##. -.......#...#...###.#..#........ -..#..###......##..##........... -.#..#......##..#.#.........#... -...#.......#........#...#.#.... -...#....#..#....#.....##....... -............#......#..........# -.#.......#......#.#....#..#.#.. -##.........#.#.#..........#.... -....##.....#................... -.......#..#........#........... -....##.#..#......###.......#... -....#....#...#.#......#...#...# -.......#.....##..#....#...#.... -#...#........#.........#..##... -...........##.........#.#...#.. -....................#....#.##.. -.#..#..#.........#....#..#..##. -......................#........ -..###....#.......#.....###.##.. -......#......#.......#.....#..# -.....#...#.##...#......#....#.. -.....#.....##.............#.... -....#......##..#....#.......#.. -.##....#..##......###....#..#.. -...###.#.............##...#.#.. -.....#.....#.....#...#..#.#.... -..#.#.....###......#.......#... -..........#.##......#.........# -..##..#.......................# -........#......#............#.. -#..#..#..#.#......#..#....#.... -...##......#.............#....# -...........#..#..##.......#.... -.....#.........#.#..#.......... -##...#.......#.#....#..#..#.... -#.#.#...........#.##.#.#..###.. -#..#...........#.........##.... -............#.#..............#. -.#....#....##.#...........#..#. -....#...#..#...#....#....#..... -....#....#...#..#......#....... -.#.#.........#.......#.##...... -.#..##...#........#...........# -##...#..#...#...#.....#...#.... -....###.#..#.......##.#..#...#. -...##.......####...##.#........ -#....#....#.#............#..#.. -#.#.#...#...................##. -##......#...........#.......... -#..#..#....#.#...#......#...... -.##...#.....#...#........#..... -..#............#..............# -###........#..#....#...#......# -###..##......#.##...........#.. -........#......#..#.....#...... -...#..........#..#...........#. -....#..#..#....#........#....#. -.#.................#####..##..# -.....#...##..#..........#.##... -..#..............#...####...... -.....#.##..................#.#. -...#.#..#..#........#.......... -...........#....#.#..#......... -.....##.......#......#..#.#.#.. -...#.............##...#........ -...............#.......##.##.## -.....#........#........#.#..#.. -...#..#.........#...##...###... -...#.#.............###.#.....#. -.#..........#......###.#.#..... -....##..##.............###..... -..#..#.#...##...#.......##..... -..........###........#.....#.#. -#.#....#..#..#......#...#...#.. -.........#......##.......#.#..# -...#.....#.........##..#..#.... -.....##.#..##.##..##........... -...#.#.##....#..#..#......#..#. -#....#....#.............#...##. -#......#..#.####.#.##.#....##.. -##.#.#....##..................# -.....##......#.......##.......# -..#......#.#..#...##......##... -..#....##....#.........#..##... -.###.....#....##...........#... -.........#......#.#........#... -...#...#..#.#....######.#..#... -###......#.#.#.........##.#.... -.....#...#.........#...#....... -....#.............#.#.........# -..##...#...#.......#......#.... -.....#...#.#...#...#..#........ -.#......#...................... -...###..#..#....#...##.#....... -.#.#.....##...#...#.....#...##. -.....###..###....##............ -.....##....#..#.....#.##....... -#........#.........#...#..#.... -...#.#.........#..#.......#.#.. -....#.#....##.....#..........#. -.#..#....#..#.#..#..#.........# -#...#....#..............#...... -.........#.....#.##...##...###. -.....#....##............#..#... -.....#.#...........#..#....#... -.#..........#...#......#.....#. -.#...........#.....#..#........ -..............#......##...#..#. -...#.........#..#....#..##...## -..##...#..................#.... -#.....#.................#...... -...#......#..#..........#.#.... -......#..#.....#.....##...#..#. -......#........#..........#.... -...##.##....#..##.#..........#. -..........#..#.#.##............ -..##........................#.. -.....#.#.#......#....#....##... -#....#.........#........#...... -.##.......#...#...#........##.. -....##......#....#.#..........# -..#.......#..............#..... -.....#......#.#...#..#.#.#....# -.....#..#........#.##.##....... -##........#..........#......... -.....#..##....#.#......###..##. -#.#...##.........#.#.....#..#.. -#....#.#...#........#.....#..#. -........................#...... -....###......#............#...# -...#..##......#..##.........#.. -.............#...#......#..#..# -....#......#....#...........#.. -..#.#.####.#.....##........#..# -#..#...#..#..#.......#.#..#.... -..#..#..#....#.#.........##..#. -.......#......#.#............#. -...#.............#.#.....#..... -...#.#.........##...#.#.......# -........#...#...........##...#. -..........#....#......#....##.. -..........#...........#........ -...#..#...#..........#......#.. -......#......#....#.....#..#.#. -........##.................#..# -.#........#.#...........#...... -#...#........#.#.#.....#.#.#... -.........#........#..#..#....#. -##........#..........#....#..#. -.#.##...........#..#.#..##....# -.......#.#....#..#......#...... -..#.....#........##..#......### -..#...#..................#....# -......#...#..#.##.......#...... -........#...#.#................ -.........#............#........ -..#.....##....#.#..##.......... -#.....#..........#....#........ -....#.#...#...##....#.....##... -..#.#.......#.............#...# -...##..............#......#.... -#......#...#................##. -.#.#...#.#..#.................. -...##.......#...........#.#.#.. -#......#.#.#........#.##...#### -.......#..#.#.........#.#.##..# -..............#....#.........#. -...........#.#..#....##......#. -#.............#...##..#.......# -.........#............#...#.##. -.......#.........#.#.....#..#.. -........................#.#.##. -#......#.#......#.........#.... -...#.......#.......#.....#..... -#..#....#................#...#. -........#.#..##......#......... -#..#...##....##....##.........# -.......#...#...###............. -#.#..#........#.#.#............ -#.....#........##.........#.#.. -.#..........#....#.#....###.... -.#.....#...#.#........#..#.##.. -...#.##......#..#.............# -..##..#.#...................#.. -.....#....#...#.#...#...#...... -.....#..#.#....#.#............. -#.#....#.#.##..###..........#.. -........#.#.............#..#... -.........#.......#............. -.##.#............##...#........ -......#................#....... -...............#..#...........# -...#.......#...#.##.....#....#. -##..##..#..........#........... -.##.#.......#...#..#...#...#... -....#..#...........#....#.##... -.#........#........#....#...... -.......#...#.##.#..#.#..#...... -.#..#......#....#...##....#.#.. -......#...##.#.....##.###.....# -.#....#..#......#...#.#.....#.. -#............#....##...##.##... -#...#.#....#...#.......##...##. -#...........#.##..#....#.....#. -...#..#...#.........#.......#.. -.#....#.....#............#.#..# -.#.....#.#...#.#....##......### -..#..#.#.#...#..#.............# -...#...#..#....#........#...##. -.......#.....#...##...........# -#.##.................#...##...# -..............##........#.....# -............#...#..#.......#.#. -#.#.....#.........#...#......#. -#.###..#......#..#..#...#.....# -.....#.......#................. -........#..#......#.#...#...... -#.......#..#........#...#..#... -..#...#.......##.............#. -#.......#.......##...#......... -.........#....#.#..##.....#...# -..#.....#.#.......#....#....... -...#.......#.....#..##.#..#.... -....#.......#.#.#.............. -.#..#......#........#.#..##..## -....#...#.##.#...#....##...#... -#..##..#.....#.......#......... -....#..#..#.#............#..... -#.......##...##..##............ -............................... -....#.......#.##...#.....#.#... -...#........#....#.#..#..#..... -##.......#.....##.#.#....#....# -#.............#...........#.##. -#...........#.#..........#..... -#..#....#....#.#.........#.#... -......#.#.#..#.#.#............. -...#.....#........##....#...... -..#...#...#.#.......#......#... -.##........#...#..#..........#. -..#...........#..##.....##..... -............#..#.#...#.....#... -..........#....##.......#...... -....#....#.................#..# -....#...............#.........# -..#.#...#......#..........##... -.....#...........#.........#..# -.......#.....##.....#.#........ -.#.#..........#....#........... -.#..##....#........#....#...... -....#.#..#.......#..#.........# -..#....#.....#......#..#....... -......#........#.......#...#.#. -.......#.......#....#.....##... -....##........#..#...#.#..#...# -.#......#...........##....#.... -##....##......#.......#.......# -.##....#.##......#.......##..#. -...#..#.#.#.......#..#.###..... -..........##....#..#.##........ -...#........###.#..#........#.. -.....#....#..##....#.....#....# -#..........#..........#.#....#. -..#....#.....#..............#.. -#..................#......#.##. -.#...#.#.....#.........##...... -...#...........#.....#......#.. -......#.....#.#..##......##.... -...#....###..#.....#..#..##..## -......#.......##..#..#......... -#..#.#....#.#..#..........##.#. -..#..#..##..#.#.#.#.....#...... -..#.#...#..#.....###.#......... -##.#.#......#........#.####.... -.............#..#..#....#...... -...##..........#.......#.#....# -..#.....................#...... -..#..#...##...#.##........#.... \ No newline at end of file diff --git a/2020/day-3.ts b/2020/day-3.ts deleted file mode 100644 index aeb2bfb..0000000 --- a/2020/day-3.ts +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env node - -import { createInterface } from 'readline'; -import { createReadStream } from 'fs'; - -const dxs = [1, 3, 5, 7]; - -const counts: {[dx: number]: number} = dxs.reduce((r, v) => ({...r, [v]: 0}), {}); -let countDY2 = 0; - -let xDY2 = 0; -let y = 0; -const xs: {[dx: number]: number} = dxs.reduce((r, v) => ({...r, [v]: 0}), {}); - -const rl = createInterface(createReadStream('day-3.input')); -rl.on('line', line => { - for (const dx of dxs) { - counts[dx] += line[xs[dx] % line.length] === '#' ? 1 : 0; - xs[dx] += dx; - } - if (y % 2 === 0) { - countDY2 += line[xDY2 % line.length] === '#' ? 1 : 0; - xDY2++; - } - y++; -}); -rl.on('close', () => { - console.log(`Saw ${counts[3]} trees`); - - console.log(`Part2: ${counts[1] * counts[3] * counts[5] * counts[7] * countDY2}`); -}); \ No newline at end of file diff --git a/2020/day-4.input b/2020/day-4.input deleted file mode 100644 index 75b3941..0000000 --- a/2020/day-4.input +++ /dev/null @@ -1,1031 +0,0 @@ -byr:1937 -eyr:2030 pid:154364481 -hgt:158cm iyr:2015 ecl:brn hcl:#c0946f cid:155 - -cid:279 -eyr:2029 -pid:675014709 ecl:amb -byr:1985 hgt:179in hcl:z iyr:2025 - -iyr:2011 hgt:181cm hcl:#341e13 pid:282499883 byr:1953 -eyr:2023 -ecl:brn - -eyr:2040 iyr:1984 pid:2371396209 byr:1951 cid:283 hgt:164cm -hcl:#623a2f - -iyr:2014 byr:1966 hgt:153cm pid:900693718 eyr:2020 ecl:gry hcl:#866857 - -eyr:2020 hgt:162cm -byr:1939 pid:900852891 iyr:2020 -ecl:oth hcl:#b6652a - -iyr:1956 -hcl:2385ac -hgt:167in -ecl:#9b82e8 -eyr:2003 -cid:214 byr:2012 pid:483285062 - -cid:146 byr:1938 hcl:#c0946f pid:136823471 -hgt:180cm iyr:2011 -eyr:2020 ecl:gry - -cid:100 hgt:187cm -byr:1973 ecl:blu -iyr:2020 -hcl:#888785 eyr:2030 -pid:386799181 - -ecl:#dbba4f -hcl:z iyr:2028 pid:193cm -byr:2029 -eyr:1962 hgt:113 - -cid:269 byr:1928 pid:604152679 -iyr:2017 eyr:2027 -hcl:#c0946f -hgt:189cm -ecl:blu - -pid:653548437 hcl:z cid:166 iyr:2011 eyr:1967 -hgt:162 ecl:xry byr:2019 - -byr:1979 ecl:hzl iyr:2018 hcl:#7d3b0c -eyr:2026 -pid:981366150 hgt:151cm - -pid:055334062 cid:272 eyr:2025 ecl:grn iyr:2016 hgt:159cm hcl:#a97842 byr:1989 - -eyr:2033 -hgt:170cm ecl:brn pid:#299cf2 hcl:#602927 byr:2004 iyr:2023 - -iyr:2020 cid:273 -pid:038972962 -hcl:#c0946f hgt:152cm -eyr:2021 ecl:blu byr:1986 - -pid:015622106 hgt:154cm iyr:2012 byr:1922 -eyr:2028 hcl:#9dc667 ecl:blu - -iyr:2017 eyr:2025 hgt:179cm cid:324 -pid:579870519 byr:1934 - -hcl:#6b5442 eyr:2021 -pid:104071480 ecl:brn -hgt:162cm cid:89 byr:1949 -iyr:2017 - -pid:388871409 cid:163 hgt:190cm ecl:amb eyr:2022 iyr:2019 byr:1963 hcl:#fffffd - -cid:190 byr:1968 iyr:2018 -hgt:155cm hcl:#6b5442 ecl:grn -pid:891458997 eyr:2030 - -hcl:z -cid:103 iyr:2026 hgt:171 byr:1979 -pid:076174078 -eyr:2031 ecl:#fc4638 - -hcl:#f8063e pid:684921958 ecl:gry eyr:2020 iyr:2011 -byr:1958 hgt:189cm -cid:131 - -ecl:gry cid:90 iyr:2010 hgt:165cm -pid:683095019 byr:1953 -hcl:#341e13 -eyr:2030 - -pid:000303662 -ecl:amb iyr:2014 hcl:#733820 byr:1964 hgt:184cm cid:149 -eyr:2027 - -hcl:#341e13 hgt:150cm byr:1999 eyr:2022 pid:950260967 cid:72 -ecl:grn iyr:2012 - -cid:159 byr:1987 -hcl:#623a2f pid:144877169 eyr:2021 ecl:brn hgt:164cm - -pid:759578668 -cid:235 ecl:amb hgt:154cm -eyr:2023 byr:1941 hcl:#fffffd -iyr:2023 - -pid:18101245 hcl:z hgt:172in iyr:1947 byr:1956 ecl:grn eyr:1964 - -eyr:1980 pid:#8d62b1 ecl:#3e8868 cid:235 -iyr:1978 hcl:#efcc98 -byr:2025 hgt:181in - -hgt:64cm hcl:3bc533 iyr:2019 byr:2015 pid:158cm eyr:2027 ecl:#1abbd7 - -eyr:2020 iyr:2011 -pid:739854643 byr:1941 hgt:179cm hcl:#602927 ecl:gry cid:330 - -hcl:#a97842 iyr:2011 hgt:167cm pid:527353688 byr:1927 cid:256 eyr:2026 ecl:grn - -iyr:2011 pid:350783151 hgt:168cm -byr:1961 ecl:amb hcl:#341e13 -cid:181 - -eyr:2025 hgt:160cm -ecl:brn hcl:#cfa07d pid:136929481 -iyr:2017 - -ecl:oth byr:1994 iyr:2020 hgt:162cm pid:578918570 eyr:2027 hcl:#fffffd -cid:325 - -hgt:63in byr:1925 -ecl:amb iyr:2014 cid:224 -hcl:#341e13 pid:208286938 - -ecl:#76434f hgt:97 -hcl:z eyr:1968 pid:#871dc8 iyr:1955 -byr:2007 - -byr:2011 -eyr:1962 hcl:9ac7b8 pid:6836105558 -ecl:#d7084f -iyr:2023 hgt:76cm - -eyr:2016 iyr:2030 hgt:107 pid:948192703 byr:2013 -hcl:b80af7 ecl:#d47439 - -eyr:2027 iyr:2017 -pid:#27d2a6 byr:1921 ecl:brn hcl:#c0946f hgt:59in - -byr:1982 hcl:#ceb3a1 ecl:brn eyr:2020 hgt:63in -iyr:2017 - -ecl:brn hgt:152cm byr:1962 -iyr:2013 -pid:381950515 hcl:#2afabd eyr:2020 - -hgt:158cm ecl:gry pid:252068098 -cid:281 eyr:2023 byr:1950 iyr:2016 -hcl:#ceb3a1 - -byr:1922 -hgt:187cm cid:74 -hcl:#a97842 -ecl:amb -pid:045338811 -eyr:2025 iyr:2019 - -hgt:176cm eyr:2022 iyr:2019 byr:1938 ecl:blu pid:610286298 -hcl:#a97842 - -iyr:2028 byr:2025 -eyr:2039 pid:72530856 ecl:#a819ad hgt:69 hcl:z - -iyr:2018 eyr:2030 -hcl:#8b1e1f ecl:hzl byr:1971 -pid:189005628 - -pid:531154383 eyr:2020 hcl:#733820 ecl:oth -hgt:72in -iyr:2016 -byr:1983 - -hgt:178cm hcl:#623a2f pid:562756202 -eyr:2020 -byr:1929 ecl:oth -iyr:2013 - -iyr:2013 byr:1983 pid:510998389 ecl:gry -cid:99 hcl:#a97842 - -ecl:gry eyr:2026 -cid:202 hgt:191cm byr:1981 -pid:414853225 -hcl:#7d3b0c - -hcl:#866857 byr:1951 eyr:2020 hgt:169cm pid:844496997 -iyr:2016 ecl:brn - -pid:083641628 iyr:2019 eyr:2030 -byr:1938 ecl:hzl hcl:#b6652a hgt:68in - -hcl:#18171d -byr:1981 -pid:425911593 cid:309 eyr:2026 ecl:brn hgt:168cm - -hcl:c84fda pid:#80d5e6 byr:1925 hgt:162cm iyr:2026 -eyr:2036 ecl:#62c166 - -pid:461660733 eyr:2028 -hgt:167cm ecl:hzl hcl:#cfa07d iyr:2010 -cid:183 - -eyr:1930 byr:2021 iyr:2016 pid:163cm -hcl:79428f cid:136 -ecl:amb - -hcl:#efcc98 hgt:176cm eyr:2022 ecl:brn iyr:2013 pid:541033681 byr:1952 - -hgt:59cm -ecl:#d9b0bc pid:#3ab4b4 hcl:7aa29f -eyr:2034 -byr:2011 cid:266 iyr:2004 - -byr:1991 hcl:#cfa07d cid:259 hgt:67cm eyr:2024 pid:631601343 ecl:brn iyr:2011 - -byr:2020 -ecl:gry iyr:1944 -pid:421649652 hgt:107 -hcl:6d8593 eyr:2026 - -ecl:blu -byr:1953 hgt:66in hcl:#888785 eyr:2021 pid:174284708 - -ecl:#8f2c20 -pid:27713962 iyr:2010 cid:149 byr:1952 hcl:#866857 eyr:2030 -hgt:186cm - -eyr:2023 byr:1989 ecl:blu -hcl:#18171d pid:480641 iyr:2020 -hgt:74in - -hcl:#efcc98 -eyr:2023 hgt:157cm byr:1968 -iyr:2013 -ecl:amb pid:436599087 - -eyr:2021 -hgt:175cm hcl:#efcc98 ecl:hzl pid:701245439 -byr:1943 iyr:2015 - -hgt:164cm pid:310546869 -eyr:2021 hcl:#b6652a ecl:oth iyr:2011 cid:181 -byr:2001 - -byr:2016 hcl:94f4b9 eyr:1922 hgt:155cm ecl:hzl iyr:2009 pid:83440078 - -iyr:2014 hgt:60in -eyr:2031 -hcl:#c0946f -byr:1948 ecl:grt pid:117909137 - -byr:1965 hgt:186cm iyr:2010 cid:117 hcl:#602927 pid:806868279 -eyr:2029 -ecl:grn - -ecl:amb hgt:187cm hcl:#c0946f byr:1935 -cid:139 iyr:2019 eyr:2023 - -pid:925865182 -byr:1952 hgt:158cm hcl:#619e03 ecl:gry eyr:2026 -iyr:2016 - -iyr:2012 hgt:73in -cid:199 -byr:1959 -ecl:hzl hcl:#fcd2f7 pid:268810283 - -eyr:2025 -pid:317239854 ecl:brn byr:1955 hcl:#fffffd cid:220 hgt:175cm -iyr:2015 - -ecl:blu -byr:1939 hcl:#3332c0 -iyr:2019 pid:832588457 eyr:2030 hgt:192cm - -hgt:64cm cid:326 ecl:oth byr:2025 eyr:2025 hcl:z iyr:2012 pid:0394683801 - -ecl:amb byr:1966 -pid:734257450 hgt:65in hcl:#fffffd iyr:2018 eyr:2025 -cid:287 - -cid:249 -eyr:2034 ecl:#7b7bf5 byr:2009 pid:171cm hcl:709fe4 - -hcl:d7c488 ecl:#b9bbb2 -pid:55277333 -cid:90 byr:2022 iyr:1978 -hgt:69cm eyr:1981 - -hcl:z -byr:1949 pid:057966198 eyr:1941 -iyr:2025 - -hgt:168cm ecl:hzl hcl:#866857 iyr:2011 pid:052204052 eyr:2030 -byr:1970 - -pid:318707043 eyr:2029 ecl:hzl hcl:#888785 -byr:1932 iyr:2010 -hgt:166cm - -hcl:z iyr:2010 ecl:oth byr:2006 cid:120 pid:#15d5ef eyr:2039 hgt:73cm - -hcl:96c534 hgt:193in eyr:2036 byr:2008 ecl:#090691 cid:109 pid:603339169 iyr:2027 - -iyr:2029 -ecl:utc -pid:5845500732 hcl:2a32b8 -byr:2009 eyr:2040 -cid:305 hgt:71cm - -byr:1994 iyr:2015 -eyr:2026 -hcl:#623a2f pid:678627790 -hgt:176cm ecl:blu - -byr:2005 hcl:z -ecl:zzz pid:#47729a eyr:2039 hgt:62cm iyr:1983 - -hcl:#cfa07d ecl:blu -iyr:2014 eyr:2025 pid:824483836 hgt:174cm byr:1933 - -hgt:70in -iyr:2010 cid:53 eyr:2023 pid:093704222 ecl:amb hcl:#a97842 byr:1945 - -ecl:brn hcl:#602927 byr:1986 eyr:2029 -pid:422160398 -cid:134 -hgt:156cm -iyr:2020 - -iyr:2014 hgt:187cm byr:1921 eyr:2022 ecl:amb - -pid:765750572 eyr:2021 -ecl:hzl -iyr:1997 hgt:66 - -iyr:2016 -ecl:blu -cid:335 -hgt:175cm pid:297297703 hcl:#b6652a -eyr:2030 - -hgt:64in hcl:#866857 pid:159cm byr:1972 -cid:321 eyr:2021 ecl:brn -iyr:2017 - -pid:884038003 -iyr:2016 hgt:188cm ecl:grn -byr:1928 eyr:2027 hcl:#341e13 - -pid:020315021 hgt:60in ecl:amb iyr:2018 -hcl:#602927 -eyr:2028 -byr:1935 - -byr:1946 eyr:2021 hcl:#efcc98 iyr:2015 -cid:52 -hgt:177cm -pid:841348804 - -ecl:gry eyr:2027 -byr:1959 pid:482204272 -hcl:#888785 -iyr:2013 - -hcl:#623a2f -eyr:2027 iyr:2011 hgt:189cm pid:767923916 ecl:hzl -byr:1987 - -hgt:152in hcl:#efcc98 ecl:hzl eyr:2030 byr:1971 iyr:1978 pid:499148724 -cid:194 - -pid:#87513f hcl:e2a5de byr:2015 iyr:2016 hgt:155cm eyr:2024 -ecl:gry cid:123 - -byr:1977 -iyr:2028 -hcl:#888785 pid:69801913 eyr:2026 hgt:165in ecl:brn - -byr:1938 hcl:#efcc98 hgt:154cm pid:621714851 eyr:1972 ecl:gry iyr:2014 cid:161 - -hcl:#a97842 -hgt:184cm ecl:oth pid:009682326 -cid:233 eyr:2023 iyr:2019 byr:1982 - -hcl:#ceb3a1 pid:700761574 eyr:2020 byr:1940 iyr:2017 -ecl:gry hgt:76in - -iyr:2017 cid:73 -ecl:hzl -hcl:#efcc98 pid:363441284 -hgt:177cm byr:1924 eyr:2028 - -hcl:#a97842 eyr:2023 byr:1989 pid:589573553 -ecl:oth -iyr:2017 hgt:162cm - -ecl:oth -byr:2001 hgt:167cm hcl:#18171d eyr:2028 iyr:2015 pid:253666913 - -byr:1943 ecl:amb -hcl:#888785 pid:163cm iyr:2025 hgt:76 eyr:2026 - -byr:1963 eyr:2030 -hgt:158in iyr:2023 pid:399153486 hcl:#733820 - -pid:43290252 hgt:167cm cid:302 iyr:2016 hcl:f81436 -byr:1992 ecl:gry -eyr:1922 - -pid:487300118 hgt:167cm hcl:#888785 -iyr:2018 ecl:oth cid:286 byr:1971 eyr:2021 - -eyr:2036 -hgt:94 -byr:2013 -cid:162 hcl:37408d pid:527721797 ecl:dne -iyr:2022 - -hcl:5e67df byr:1973 pid:48217944 hgt:65in eyr:2023 -iyr:2001 ecl:gry - -hcl:717ef8 eyr:1996 pid:154cm ecl:#e2c90e -iyr:2028 -byr:2009 hgt:184cm - -iyr:2015 pid:549968053 hcl:#efcc98 -hgt:151cm eyr:2025 -byr:1993 -ecl:gry - -hgt:165cm ecl:gry -iyr:2020 -byr:1927 hcl:#602927 pid:278946330 -eyr:2027 - -eyr:2031 -ecl:#b01aae pid:151cm -cid:188 iyr:2025 -hgt:60cm byr:2015 - -eyr:2028 pid:928740840 -byr:1931 -hgt:191cm iyr:2014 cid:305 -hcl:#6b5442 -ecl:oth - -hcl:#7d3b0c cid:283 byr:1923 ecl:amb -pid:781290431 iyr:2019 -eyr:2021 -hgt:191cm - -byr:2027 -pid:51702036 -iyr:2028 hgt:165in ecl:gry hcl:z -eyr:2036 - -byr:1971 -ecl:blu iyr:2012 pid:986042111 -eyr:2021 hcl:#888785 -hgt:68in - -hgt:183cm byr:2030 -iyr:2013 -cid:209 pid:989002507 -ecl:hzl eyr:2028 hcl:59c2ce - -ecl:gry iyr:2020 pid:895856989 hcl:#888785 -hgt:185cm byr:1964 eyr:2025 - -ecl:gry -hgt:183cm cid:97 hcl:#93be9b eyr:2021 -byr:1995 pid:668647173 - -hcl:#733820 eyr:2027 -byr:1977 pid:242773849 hgt:184cm iyr:2017 -cid:76 ecl:brn - -hgt:167 hcl:z byr:2012 eyr:2027 -pid:590438786 ecl:hzl -cid:101 iyr:1994 - -iyr:2015 -hcl:#888785 eyr:2024 -ecl:blu pid:279218875 cid:178 byr:1944 hgt:74in - -ecl:oth cid:334 pid:169599381 -hcl:#7d3b0c eyr:2028 hgt:172cm iyr:2010 - -eyr:2033 byr:1973 cid:333 iyr:2019 hcl:z ecl:utc -hgt:178cm pid:#e7abc0 - -eyr:2026 ecl:blu cid:264 byr:1998 hgt:177cm hcl:#602927 -pid:770052780 -iyr:2019 - -ecl:blu -iyr:2016 cid:232 eyr:2023 -pid:643597545 hgt:167cm byr:1986 hcl:#cfa07d - -pid:017818204 -iyr:2017 eyr:2028 hgt:168cm hcl:#602927 byr:1931 ecl:oth - -byr:1984 ecl:grn hgt:191cm hcl:#efcc98 pid:408382086 -iyr:2010 eyr:2025 - -hgt:158cm ecl:#25e195 byr:1929 pid:0367744553 eyr:1957 iyr:2017 -hcl:z - -hgt:168cm byr:1977 pid:006609828 -eyr:2024 -iyr:2015 -ecl:amb hcl:#b6652a - -pid:635167847 iyr:2010 hcl:#18171d hgt:163cm ecl:grn -eyr:2026 - -pid:423029177 byr:1995 -iyr:2014 ecl:hzl -hgt:185cm hcl:#c0946f eyr:2024 cid:230 - -pid:#3e3109 ecl:#a8a0aa iyr:2020 hcl:#733820 eyr:2021 byr:2010 hgt:179in - -iyr:2017 byr:1938 eyr:2022 hcl:#733820 ecl:amb hgt:157cm pid:162425330 - -hgt:160cm -cid:339 byr:1938 -hcl:#341e13 -eyr:2025 iyr:2015 -pid:562755634 - -cid:283 byr:1954 ecl:blu hcl:#ceb3a1 hgt:169cm iyr:2013 pid:616439723 - -pid:830940520 eyr:2022 -byr:1981 hgt:193cm hcl:#18171d iyr:2013 -cid:117 - -hcl:#866857 iyr:2019 ecl:hzl byr:1962 hgt:72in eyr:2020 - -byr:2015 pid:4530685490 ecl:#c7604e hcl:z -hgt:151 eyr:1972 iyr:1948 - -pid:0800674852 hcl:z -ecl:#2a275e hgt:61cm -iyr:1950 eyr:1938 - -iyr:2028 -eyr:1998 -pid:#c604ca -hgt:122 hcl:z -ecl:dne cid:160 byr:2018 - -hcl:z -cid:67 iyr:2029 -byr:1973 -ecl:amb eyr:2030 -hgt:66 - -ecl:hzl -pid:483557353 eyr:2021 -hgt:172cm iyr:2011 -hcl:#888785 -byr:1963 - -eyr:2030 ecl:brn hcl:#fffffd byr:1969 -hgt:161cm pid:632930895 -iyr:2017 - -iyr:2015 byr:2000 -pid:525557240 hgt:156cm eyr:2029 -ecl:brn hcl:#64bf85 - -byr:2007 -iyr:2012 eyr:2029 ecl:#7c1d6f pid:612320497 hgt:165in - -eyr:2026 ecl:grn cid:93 -hcl:#888785 hgt:134 pid:745552484 iyr:2019 byr:1999 - -byr:2001 pid:984678649 hgt:173cm ecl:oth iyr:2012 cid:345 hcl:#fffffd -eyr:2028 - -hcl:#341e13 pid:308853935 -byr:1972 hgt:160cm iyr:2012 eyr:2026 -ecl:amb cid:97 - -hcl:z hgt:151 -ecl:grn pid:132866718 -iyr:2021 byr:1932 -eyr:2024 - -eyr:2027 byr:1923 -ecl:oth hgt:174cm hcl:#733820 -pid:099185839 -iyr:2017 - -iyr:2017 ecl:gry byr:1941 -hgt:74in -pid:540930352 -hcl:#888785 eyr:2023 - -hgt:161cm cid:277 -hcl:#866857 -byr:1928 -eyr:2030 ecl:blu -iyr:2020 pid:358953579 - -hgt:155cm eyr:1930 -iyr:2015 ecl:utc -pid:163cm -byr:2008 hcl:#733820 cid:156 - -byr:1946 hgt:164cm -cid:234 iyr:2015 -pid:168804387 eyr:2025 -ecl:hzl hcl:#a97842 - -hgt:184cm -hcl:#7d3b0c byr:1996 cid:193 iyr:2011 ecl:amb eyr:2030 pid:940497049 - -hcl:#733820 iyr:2016 hgt:168 -eyr:2020 -cid:118 pid:9871436 ecl:gry - -pid:416683862 -hgt:162in -hcl:#602927 byr:2027 -eyr:2027 ecl:gmt - -ecl:#771e11 -iyr:2024 -cid:81 pid:741843390 -hcl:#866857 byr:2012 eyr:1964 -hgt:157in - -pid:720946735 -byr:2002 hcl:#18171d iyr:2026 hgt:70cm -ecl:brn eyr:2025 - -byr:1987 hcl:#623a2f -hgt:165cm pid:087526326 ecl:grn -iyr:2017 eyr:2021 - -byr:2014 hgt:193cm -iyr:2018 hcl:z -eyr:2027 pid:792398819 - -cid:233 -hcl:z ecl:#18002d hgt:174cm iyr:2027 eyr:1944 - -pid:142615460 ecl:blu eyr:2021 -hcl:#c88693 iyr:2017 cid:182 hgt:152cm byr:1966 - -hcl:z hgt:65cm -eyr:1944 ecl:dne byr:2029 pid:1066768764 -iyr:2015 -cid:149 - -hcl:z pid:25144284 hgt:152in -byr:2009 -cid:276 eyr:2037 -iyr:2010 ecl:gmt - -cid:88 hcl:ed6b8a ecl:xry hgt:178in pid:36832491 byr:2020 iyr:2012 eyr:1993 - -byr:1972 iyr:2009 pid:324213657 hgt:160 hcl:z cid:259 eyr:2021 ecl:grn - -hcl:#7d3b0c pid:164496070 eyr:2024 ecl:brn hgt:165cm - -pid:955035528 -byr:1967 eyr:2021 iyr:2015 hcl:#fffffd hgt:156cm -cid:237 -ecl:blu - -hcl:z -eyr:2038 iyr:1973 ecl:grt hgt:193in -pid:41385449 byr:2011 -cid:119 - -byr:1934 pid:713339056 hgt:157cm cid:250 iyr:2016 ecl:blu hcl:#866857 eyr:2026 - -hgt:186cm byr:2012 -eyr:2022 -iyr:2013 hcl:#733820 pid:226693031 ecl:hzl - -cid:118 pid:56750275 hcl:#cfa07d iyr:2028 eyr:2033 byr:1933 hgt:166cm - -byr:1973 -ecl:hzl hgt:167 hcl:z -iyr:2015 pid:70648423 - -byr:1929 -iyr:2012 pid:083005744 ecl:brn hgt:162cm -eyr:2024 -hcl:#cfa07d - -hcl:#623a2f hgt:174cm -eyr:2026 iyr:2020 -ecl:grn -byr:1981 - -cid:236 byr:1979 iyr:2013 ecl:amb eyr:2030 hcl:#6b5442 pid:768869830 - -hcl:#341e13 byr:1998 iyr:2020 -pid:857980686 -ecl:hzl hgt:175cm eyr:2028 - -hgt:169in -cid:305 eyr:2023 -ecl:gry pid:833031763 hcl:#ceb3a1 iyr:2015 byr:1974 - -pid:370671195 hgt:162cm -iyr:2018 ecl:oth byr:2001 hcl:#7d3b0c -eyr:2021 - -eyr:2026 -ecl:brn -cid:288 -hcl:#866857 iyr:2010 byr:1922 -pid:309109383 - -byr:1949 iyr:2015 pid:832774982 eyr:2029 -hgt:182cm -hcl:#b7144c ecl:amb - -eyr:2029 iyr:2020 -hcl:#c0946f -pid:953788134 -byr:1954 hgt:167cm - -pid:981508704 eyr:2023 iyr:2013 hgt:66in cid:68 hcl:#fffffd byr:1996 ecl:oth - -iyr:2011 byr:1932 cid:232 eyr:2030 -hcl:#c0946f -hgt:169cm pid:994763987 -ecl:hzl - -ecl:gmt eyr:2031 hcl:z -byr:2006 cid:86 hgt:59cm iyr:1998 pid:#349a7f - -hcl:#7d3b0c iyr:2013 pid:549500594 eyr:2024 byr:1971 ecl:oth -hgt:153cm - -iyr:2015 -byr:1940 pid:798926275 eyr:2027 -hcl:#cfa07d -hgt:158cm ecl:amb - -ecl:brn pid:077141823 -eyr:1945 iyr:2023 hcl:#602927 byr:1956 -hgt:152 - -iyr:2022 -byr:2007 -hcl:f87f81 pid:8404831740 eyr:2033 hgt:170cm -ecl:gmt - -iyr:1958 -ecl:dne hcl:840fbe -cid:55 eyr:2032 pid:19403738 hgt:170cm -byr:2029 - -ecl:brn pid:864743117 -eyr:2025 -hgt:188cm byr:1934 hcl:#623a2f -iyr:2011 - -iyr:2010 pid:877675472 hcl:#7d3b0c eyr:2027 byr:1954 hgt:182cm -ecl:oth - -iyr:2015 hcl:#a97842 pid:719192774 ecl:brn -byr:1993 -hgt:186cm - -eyr:2021 hgt:176cm pid:395161956 hcl:#602927 -ecl:grn iyr:2020 byr:1972 - -hcl:#fffffd hgt:167cm byr:1945 ecl:grn iyr:2017 eyr:2026 - -hcl:#6b5442 ecl:gry cid:208 hgt:155cm iyr:2010 byr:1933 pid:040244553 -eyr:2029 - -iyr:1960 cid:281 ecl:#8f7c45 hcl:z pid:11609858 eyr:1955 hgt:150in -byr:1985 - -hgt:150cm byr:2002 hcl:#fffffd -pid:337375886 iyr:2011 ecl:amb -eyr:2037 - -iyr:2014 ecl:oth hgt:155cm hcl:#866857 eyr:2025 pid:614859979 cid:338 -byr:1952 - -hcl:#623a2f hgt:156cm -iyr:2010 ecl:amb byr:1997 -cid:285 -pid:225568504 eyr:2020 - -iyr:2021 hcl:#ceb3a1 ecl:#d6db5a pid:185cm eyr:2020 cid:130 byr:2009 - -byr:1956 -cid:245 iyr:1954 ecl:dne hcl:#341e13 eyr:2040 hgt:71cm pid:838134394 - -eyr:2027 -byr:1994 ecl:amb iyr:2014 hgt:168cm -cid:278 -hcl:#602927 pid:758176176 - -hcl:#941519 ecl:gry eyr:2030 byr:1921 -pid:9477831046 -iyr:2018 hgt:189cm - -cid:339 hcl:#6b5442 -byr:1972 -ecl:oth -iyr:2014 hgt:183cm eyr:2020 - -cid:165 -eyr:1926 hcl:#6b5442 iyr:1956 hgt:65cm byr:2029 -pid:9240052093 ecl:xry - -ecl:grn -eyr:2027 -hcl:#fffffd byr:1975 iyr:2011 hgt:177cm pid:825090410 cid:121 - -byr:1934 -hcl:#733820 pid:133141914 eyr:2027 -hgt:66in -ecl:amb -iyr:2010 cid:262 - -iyr:1951 -ecl:#bb9733 hcl:89fcbf -byr:2018 pid:#13265f hgt:85 -eyr:1977 - -hcl:#324bed ecl:hzl hgt:155cm -iyr:2013 byr:1942 eyr:2021 -pid:758516520 - -ecl:gry -pid:#567782 iyr:2015 hcl:276a6d eyr:2028 -hgt:60cm -byr:2005 - -hcl:#18171d hgt:191cm eyr:2030 -ecl:grn pid:748729106 byr:1922 iyr:2017 - -byr:1984 hcl:#733820 eyr:2020 iyr:2013 hgt:64in pid:444446114 -ecl:hzl - -byr:2006 ecl:dne iyr:2029 hcl:z -eyr:2023 hgt:68cm -pid:131910019 - -iyr:1976 hcl:45191a eyr:2017 hgt:68cm -ecl:oth pid:153cm byr:1968 - -ecl:gry byr:1959 eyr:2023 pid:781945569 -iyr:2015 hcl:#ceb3a1 hgt:167cm - -hgt:151cm -byr:1959 hcl:#7d3b0c -cid:76 pid:069205247 ecl:gry eyr:2029 -iyr:2013 - -pid:055193304 -hcl:#fffffd -hgt:67in ecl:grn iyr:2011 - -eyr:2026 -byr:1975 -pid:681437369 -hgt:173cm hcl:#a97842 -iyr:2017 ecl:brn - -pid:298214774 hgt:158cm ecl:hzl -hcl:#866857 byr:1993 iyr:2013 -eyr:2028 - -hcl:#b6652a eyr:2023 pid:879418046 hgt:193cm -iyr:2014 -ecl:brn - -hgt:164cm -eyr:2028 hcl:fbd462 ecl:gry -iyr:2011 byr:1938 pid:029003659 - -byr:1999 hgt:171cm eyr:2024 cid:195 pid:041799326 ecl:gry iyr:2012 hcl:#a97842 - -byr:1963 pid:7471206322 iyr:2015 ecl:brn hcl:#623a2f hgt:72cm -cid:63 - -byr:1961 -ecl:hzl hcl:#efcc98 -pid:617022365 -eyr:2020 hgt:155cm iyr:2018 - -pid:385763432 byr:1977 cid:228 hcl:#733820 eyr:2020 -hgt:163cm ecl:grt -iyr:2015 - -byr:1979 hgt:186in eyr:2037 -ecl:dne -iyr:2025 hcl:d93e3e -pid:187cm - -iyr:2018 -cid:158 eyr:2020 -byr:1929 -pid:334374178 hgt:181cm hcl:z ecl:grn - -cid:135 ecl:oth hcl:#623a2f -iyr:2017 -eyr:2024 byr:1940 -hgt:66in - -cid:92 eyr:2026 hcl:#888785 pid:827526879 byr:1990 -hgt:186cm ecl:amb iyr:2014 - -pid:575519103 -iyr:2016 byr:1964 hcl:#7d3b0c cid:252 hgt:172cm - -hcl:#c0946f -ecl:grn hgt:75in -eyr:2021 pid:426544544 - -cid:171 byr:2004 -hcl:z -hgt:191cm eyr:2028 pid:#292b3b ecl:brn - -iyr:2016 ecl:hzl -byr:2007 -hgt:167cm hcl:#653b4c cid:124 eyr:2022 -pid:#27024c - -hgt:177cm byr:2025 -hcl:z cid:303 iyr:2016 eyr:2000 ecl:dne -pid:345555418 - -eyr:2040 -hcl:70fbf6 cid:318 -byr:2027 iyr:2022 -ecl:#3a037c pid:644624005 -hgt:62cm - -ecl:brn iyr:2016 hgt:150cm pid:680594195 cid:324 hcl:#602927 -byr:1944 - -hcl:z eyr:2022 byr:2020 cid:112 ecl:dne iyr:2029 -pid:#3a3560 hgt:153in - -cid:86 -ecl:gry byr:1972 hcl:#866857 pid:758976621 hgt:188cm - -pid:#850e8b eyr:2025 hgt:163in -ecl:#71e9e2 -hcl:#623a2f - -ecl:amb byr:1958 hgt:193cm -pid:343803154 iyr:2010 eyr:2029 cid:86 hcl:#602927 - -hgt:178cm byr:1987 ecl:blu hcl:#866857 iyr:2017 -pid:222443921 eyr:2027 - -byr:1964 iyr:2001 -hgt:180cm eyr:1945 -hcl:#fffffd pid:305189916 ecl:#ac3c49 -cid:142 - -byr:1979 hgt:166cm ecl:brn -cid:202 hcl:#5311ca eyr:2028 pid:874418818 iyr:2014 - -hgt:161cm byr:1987 ecl:grn hcl:#6b5442 pid:986096798 -cid:74 -eyr:2027 iyr:2019 - -byr:1964 iyr:1979 eyr:2022 ecl:#77ada3 -hcl:#733820 -cid:56 - -hgt:185cm iyr:2010 pid:214991920 eyr:2023 cid:236 hcl:#866857 ecl:brn byr:1965 - -pid:885169578 iyr:2010 byr:1948 ecl:hzl hcl:#18171d -eyr:2025 hgt:175cm - -ecl:oth pid:34655368 -hgt:186 -byr:1968 -hcl:2653c9 -eyr:2030 iyr:2024 - -eyr:2022 iyr:2015 ecl:gry hgt:65in byr:1994 -pid:766704860 - -hcl:#c0946f cid:104 iyr:2015 -pid:739274357 -ecl:#ef45c8 -byr:1960 hgt:61in eyr:2026 - -pid:849044092 eyr:2020 hgt:186cm iyr:2014 -byr:1991 hcl:#866857 - -hgt:159cm iyr:1950 -eyr:2021 pid:325442644 hcl:#888785 -ecl:gry byr:1986 - -eyr:2023 hgt:188cm -iyr:2014 -pid:945115479 byr:1979 ecl:blu hcl:#b6652a - -eyr:2024 -cid:274 pid:390115952 byr:1934 hgt:161cm iyr:2017 hcl:#b95b0d - -ecl:#a16ec8 pid:187cm hcl:z iyr:2029 hgt:170 -byr:2008 \ No newline at end of file diff --git a/2020/day-4.ts b/2020/day-4.ts deleted file mode 100644 index 51ffb3e..0000000 --- a/2020/day-4.ts +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env node - -import { createInterface } from 'readline'; -import { createReadStream } from 'fs'; - -function between(v: number, min: number, max: number) { - return v >= min && v <= max; -} - -interface Requirement { - field: string; - isValid: (value: string) => boolean; -} - -const REQUIREMENTS_PART_1: Requirement[] = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid'] - .map(field => ({ field, isValid: value => Boolean(value)})); - -const REQUIREMENTS_PART_2: Requirement[] = [ - { field: 'byr', isValid: value => between(Number(value), 1920, 2002) }, - { field: 'iyr', isValid: value => between(Number(value), 2010, 2020) }, - { field: 'eyr', isValid: value => between(Number(value), 2020, 2030) }, - { - field: 'hgt', - isValid: value => { - const match = /^([0-9]+)(cm|in)$/.exec(value); - if (match) { - const [, v, unit] = match; - switch (unit) { - case 'cm': return between(Number(v), 150, 193); - case 'in': return between(Number(v), 59, 76); - } - } - return false; - }, - }, - { field: 'hcl', isValid: value => /^#[0-9a-f]{6}$/.test(value) }, - { field: 'ecl', isValid: value => ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'].includes(value) }, - { field: 'pid', isValid: value => /^[0-9]{9}$/.test(value) }, -]; - -let passport: Record = {}; - -let validPart1 = 0; -let validPart2 = 0; - -const rl = createInterface(createReadStream('day-4.input')); -rl.on('line', line => { - if (line.trim() === '') { - // Process current passport - if (REQUIREMENTS_PART_1.every(({field, isValid}) => isValid(passport[field]))) { - validPart1++; - } - const invalidFieldsPart2 = REQUIREMENTS_PART_2.filter(({field, isValid}) => !isValid(passport[field])).map(({ field }) => field); - if (invalidFieldsPart2.length === 0) { - validPart2++; - } else { - console.log(`Invalid fields ${JSON.stringify(invalidFieldsPart2)}: ${JSON.stringify(passport)}`); - } - // Reset passport - passport = {}; - } else { - for (const kv of line.split(/\s+/)) { - const [field, value] = kv.split(/:/); - passport[field] = value; - } - } -}); -rl.on('close', () => { - console.log(`Found ${validPart1} part-1-valid passports`); - console.log(`Found ${validPart2} part-2-valid passports`); -}); \ No newline at end of file diff --git a/2020/day-5.input b/2020/day-5.input deleted file mode 100644 index b5802a0..0000000 --- a/2020/day-5.input +++ /dev/null @@ -1,901 +0,0 @@ -BBFBBBBRRL -FBFFFFBLRL -FBFBBFFRLR -FBFFFBFRLR -FFBBFFFLRR -FFBBBFFRRR -BFBBFBFLRL -BFFFBFFLRR -FBBBFFBLLR -BBFFBBFRRL -BFBBBBBRLR -FBBBBFFLLR -FFBFFFBLLR -FFBBFBFRRR -BBFBFFFRRR -FFBFFBBLLR -FBBFFBBLRL -FFBBBFBLLL -FFBFFBBLRR -FBFFBFBLLR -FFFBBBFLLL -BFBBFBFRLR -BBFBBBFLLL -FBBBFBBRLL -FFBBBBFRRL -BFBBBBFLRR -BBFBBFBLRL -FFBFFFBLRL -BFBBBBBRRR -FFFBFBFLLR -BFBFBBBLLR -FFBFBBBLRL -FFFBFBBLRR -BFFBFFFLLL -BFFFBFBLRL -BFBFFFBRLL -BBFFFFBRLR -FBBFFFBLRR -BFFFFBFLLL -BBBFFFFLLL -BFBFFBBRLL -BBFBFFFRRL -BFBBFFFRLR -BBFBFBFRRL -FBBFFBFRRL -BFBFBFFRRL -FFBFFFFLLR -FBBBFBBLLR -BBFFBFBRLL -BFFBFBBRLL -FBBFFFFRRR -BFFFBBBLRL -FFBBFFBLLL -FFFBBFFRRL -FBFBBBBLRR -FFBBBFFLLL -FBFBFFBRRR -FBBFFBBLLR -FBFFBFFRLL -BFBBBFFRLR -FBFFBBBLRR -FBFFFFBRLR -BBFFBBFLRL -FBFFBBFLRL -FBFBBFFRRR -BFBBBFBLRL -FBFBFFFLLR -FFFFBBBLLR -BFBFFBBLLR -BFFBBBFRLR -BFBBBFFLRR -BBFFFBBLLR -BFFFBBFLRL -FBFFBFBLRL -FBBBFFFRRL -FBFFFFBLLL -BFBFFBBRLR -BFBFBBBLRL -BFFBFBBRLR -FBBFBBBLLR -FFBFBFFRLL -FFFBBBBLRR -BFBFFFFLLL -BBFBFBBLLR -BFFFBBBRLR -FFBFFBFRLR -FBBFBBBLRL -BBFFFBBLLL -FFBFFBBRRR -FBBBBFBLLR -BBFBBFFRLL -BFBBBBFRLR -BBFBFFBRLR -FFBFFFFLLL -BBFBFBFRLL -FFBFFBBRLL -FBBFFFFRLR -FFBBBBBRRR -BBFFBBBLRL -BFFBBFBRLL -BFFFBBFRLL -BFFBFBFLRL -FBFFFFFRRR -BFFBFBBRRL -FBFBBBFLLR -FBFBFBBRLL -BBBFFFFRRR -BFBFBFFLRL -FFFFBFBRLL -FFBBFFBLRL -BBFFBFBLLL -BFFBBBBRLL -BFFBBBBRRR -BFBBBBFRRL -BBBFFFBLRL -FFBBFFFRRR -BFFFFFBRLR -FFFBBFBLLL -BFBFBBFRLR -FBBBFBFLRL -BFBFBFFRLR -BBFBBFFLRL -BFFFBFBLLL -BFFFFBBRLL -FFBFFFFRRL -BFFBFBBLLR -FFFFBBBLLL -FBBFFBBRRL -BFBFFFFLLR -FBFBFBFRLL -FBBBBBBLRR -BBFFFFBLRR -FFFFBFBRRR -FBBBBFBRLL -BBFBFBBLRR -FFBBFBFLLL -BFBBFFBLRL -FFFBBBBRRR -BFBBFFFRLL -BFBBBFBRRR -FFFFBBFRLR -FFBBFBFLRR -FFFFFBBLLR -BBFBBFBRLL -FBFBBBBRLR -BBFFFFBLRL -FBBFFFBLLR -FFBFFBBLLL -FFFBBBFLLR -FFFBBBFRRR -FFBBBFBRRR -FFFBBFFRRR -FFBBFFBLLR -BFBFFBFRRR -FFBFBBFLLR -BFFFFFFRRR -FFBFFBFLRL -BFFBFBBRRR -FBFBFFFRLL -BBBFFFBLLL -BFBBFBFRRL -BFFFFFBLRR -FBBBBBFRRR -FFBBBBFLRR -BBFBBBBLRR -BBFBFBFLLR -FFFFBBFRRR -FFBBBBBLLR -BFFFBFBRLR -FBBBFFBLLL -FFFFFFFRRR -FFFBFBFRRL -BFBBFBBLRR -FBBBBFBLRL -FBBBBFBRRR -BFFFFBFRRR -BFFBBFFLLL -FBBFBFBLRL -BFBBFFFRRL -FBFBFFBRLR -FBFFBFFLRR -BFFFBFBLLR -BFBBFFBRRR -BBFBBFBLLL -BFFBFFFLRR -FFFBBFFRLL -BFBBFFFLLL -BFFFBBBRLL -FBFFBBFRRR -FFBFBFBLLR -FBFFFFBLRR -FFBBFFFLLL -FFFBBBBRRL -BBFBFFFLLL -BBFFBBFLLR -BFBFBBBRRR -FBBBBFBRRL -FBFFFBFLLR -FBFBBBFRRR -BFFFBFBRRL -FBFBBBFLRL -BBFFBFFLRL -BBFBBFFLLR -FFFFBFFRLL -FFFBBBBLRL -FBBBFBFRLL -BBFFFBBLRL -FFFBFFBLRR -BBFBFBBRRL -FFFFBBBRRR -FFBBBBBLRL -FFFFFFBLLL -FBFFFFFRRL -FFFFFBBLRR -BFFFBBBRRL -FBBFFFFLRL -FFFFFBBRLR -FFBFFBFRLL -FFFBBBFRRL -BFBBBFFLRL -FFFFFBFLRR -BFBFBBBRLR -FBFBBBFLLL -BFBFFBFLRL -FFBFBFFRRR -FFBBFFFRLL -BFBFBFFLLL -FBFBFBBRLR -BFFBBBFRRL -FBFFBBBRRR -FBFBFBBLRR -BFBBBBFLLR -FFFBFFFRLR -BFBBFFBRRL -BFFFBFFLRL -BFBFBBFRRR -FBBFFBFLLL -FFFFFFBLRR -FBFFBFBLRR -FFBBBFFLRR -FBBBFFBRLL -BFFFBBBRRR -FFBFFFFRLL -BBFFFBFRRR -BFFBFBBLLL -BFBBFFBRLR -FFBFBBBLRR -FFFBFBBLLL -FFFBBFFLLL -FBBBBBBLRL -BFBFBBBLLL -BFBFFFFRRL -FFBFBBFRRR -FFBFBFBRRL -FFFBBBBRLL -BFFBFFBRLL -BBFFFFBRRL -FFBFBFBLLL -FFBFBFBRLL -FBFBBBFRRL -FBFFBBFRLR -BBBFFFFLRL -FBFBFFFRRL -FFFBFBFRLR -FBFBFBBRRL -BFBBFBBLLL -FFBBBBBRLL -BBFFBFBRRL -FFFBFFFRRR -FBBFBFBLLL -BFFFBFFRLR -FBFBFFBRLL -BBFBBFFLLL -FBBBBFFLRR -FFBBBFFLRL -FBBBFFBRRR -FFBBFBBRLR -FBFBBFFLLR -BFBBBFFLLR -FFFBBFFLRR -FBFFBFFLRL -BFBFBFFLRR -BBFBFFFLLR -FFFBBBBLLR -FFBBFFBRLL -BBBFFFBRLL -FBFFBFBRRL -BFBFFFFRLL -FBFBFBFRLR -BBFFFFFLLL -FFBFBBBLLR -FFBFBFFLRR -FBBBBFBRLR -FFBFBBBRLR -BFFBBBBLRL -FFBBBBBRLR -BFBBBFFRRR -FBFBBFBRLL -FFBFFFBRRL -BBFBFBFLLL -BFBBBFBRLR -BFBBFBFLLR -FBBFBFFRLL -FFBFBBFLRR -BFFBFBFRLL -FFBBFBBLRL -FBFBFBBLRL -BBFFFBFLLR -BFBFBBBLRR -BBFFBBBLLR -BBFFFFBRRR -BFFFFFBLRL -FBBBFBBRRR -BFBFFFBLLL -FFFBBFFLLR -BFFBBFFLLR -BBFBBBBLRL -FBBFBFFLRR -FBFBFFBLLR -BFFFFFFLLL -BFFBBFFRLL -BBFFFFFLLR -FBFFBBFRRL -FBBFFFFLLR -BFBFFBBRRL -FFBFFFBLLL -BFFFFFBLLR -FFBBBFBRRL -FFBBBBFLLR -BFBFFFBLLR -FFFFBFFRLR -BFBBFFBRLL -FFBBBBBLLL -FBBFBFFRRR -BFFFFFFLLR -FFBBBBBLRR -FFFFFBFRRR -BFFFBBBLLL -BFFFBFFRRR -FFBBBFBRLR -BFFBBBBLRR -BFBBBFFRRL -BFBFBFFRRR -BFBBFBBRLR -BFBBBBFRLL -FFBBBBFLLL -FFFBBFBLRR -FBBFBBFRLR -BBFBBFFLRR -FBBFBBBRRL -BFFBFFFRRL -BFFFFBFLRR -FFBFBBFLLL -FFBFBBBLLL -FBFFBFBRRR -FFFBFFBRLL -BFFFFBFLRL -FFFFBFFLLR -BBFBBBBRLL -FBFBBFBRRR -BFFFBBBLRR -FBFFFBFRLL -FFBBBFBLRL -FBFFFBBLRR -FFBBFBFRLR -FBBBBBFLRL -FFFFBFBLRR -BFBFBFBLRR -FFBBFFFLRL -BFFBBBFLLR -FFFFFFBRLR -FFBBBFBLRR -FBFBBFFRLL -BBFBFBFRLR -FBBFFFFLLL -BFBBFBFRRR -BFFBBBFRRR -FBFFFBFLRR -FBBFFBFLRL -BFBBFFFLRR -FFBFFFFLRL -BFFBFFBLLL -FFFBFBBRRR -BBFFBFFLRR -BBBFFFFRRL -FBBBFFBLRL -FBBFFBBLRR -FFBFBFFLLR -FFFBBFFRLR -FBBBFBBRLR -FFFFBBBLRR -BBFFBFBRRR -FBFBBFFLRL -FBBBBFFLLL -FFBFFBBRLR -BBFFFFFLRR -FFBFBFBRLR -FFBFBFBLRL -FBBBFBBLRL -FFFBFBBLRL -FBFBFFFRRR -BFFBFFFRLR -BFBBFFBLLR -BFBFFBFRLL -FBFBFBFRRR -FBFFFFBRLL -FFFFFBBRRR -FBBBFFFLRL -FFFBFFBRLR -BFBFFBFLRR -FBBFBBFRRL -BFBBBBFRRR -BFFFFBBLRR -FBFFFFFLLL -BFBFFFBRRL -FFFBFFBLRL -FFBFFFBLRR -FBBFFBFRLL -BBFBFFBLLL -BBFFBBFLLL -FFBBBFFRLL -BFBBFFFLRL -FBBFBFFLLR -FBFBFFBLLL -FFBBBFFLLR -FBBFFBFLRR -FBBFBBFRRR -BFFFFBBLLL -FFFBFFBLLR -FBFBFFFRLR -FBFBFBBRRR -FBFBBFBRRL -BBFBBFBRRR -FFFFBBBRLL -FBFFBBBLRL -BBBFFFFRLL -FBFFFBFLRL -BFFFFBFLLR -FBFBBFFRRL -BFFBFBBLRR -FBFBBBBRRL -FBFBFBBLLR -FBFFBBFLRR -FFFFBFFLLL -BFBFFFFRRR -BBFFBBBLRR -FBFFFFFLLR -BBFBFFFRLR -BFFFFBBRLR -FBFFFFFLRL -FBBBFBBLRR -BFFBBFBLLL -BFFBFBBLRL -BFFBBBFRLL -FFBFFBFRRR -BFBFBFBRLL -BBFBBFBLLR -FBFBBFBLRL -FBFFFBBRLR -BBFBFFBRLL -BBFFFBFRLR -FBBFFFBLLL -BBFBBBBLLL -BFFFFFFLRR -FBBBBBFRLL -BFFFBFBRRR -BFFFFFFLRL -FBBBBFBLRR -FBFFBBBRLR -FFBBFBFRRL -FFBBFBBRRL -FFFBFBFRRR -FFBBBBFLRL -BFBBFFFRRR -FBFBBBBRLL -FBFFBBFRLL -FFBFFFFRRR -BFFFFBBLLR -FBFBBFBLLR -BBFFBBBRRR -FBBFBBBRLR -BFBFBFFRLL -BFFBBFBLRL -BFFBFFFRRR -FFBBBFBRLL -FBFFBFFRRL -FBBBBFFRRR -FFFBBBFRLL -BBFFFBBRLL -BBFFFBBRLR -FFBBFFFRRL -BBFFBFBLRR -BBFBFFBRRR -BFBBBBBLRR -BFFBBFFLRL -BBFFFFBLLL -FFFFBFBRRL -FBBFFBBRRR -FBBBFFFLRR -FBBFBBFLRR -FBBBFBBLLL -FFFFBBFLRL -FFFFFBBLLL -BFBBBBBLLR -BFBFFFFLRR -FBFFFFBLLR -BBFFBBBRLL -FBFFBFFRRR -FFBBFBFLLR -BBFBBBFLRR -FBBBBBBRLL -FFFFFFBLLR -FFFFFBFRLR -FBFFBFBRLL -BBFFBFFRRR -BFFBFFFLLR -FFBBFBBLRR -BBFFBBBRLR -FFBBFFBRRL -FBBBBFFRRL -BFBFFFFRLR -BFBBBFBLLL -BFBFFFBRRR -FBBBFFFRLR -BFBBFFBLRR -BBFBBFFRLR -BBFFFBBRRR -FFFFBBBRRL -FFBFBBFRLL -FBFFFFBRRL -FBBBFFBRLR -FFBFFFBRRR -FBBBBBBLLL -BFFBFFBLRL -FBFFBBBRLL -BBFBBBFRLR -BFBFBFBRLR -BBFFFFBRLL -FFBBFBBLLR -FFBBFFBRLR -BBFBBBBRLR -BFBBBFBLLR -FFFFBFFRRR -BBFFFBFRRL -FBBFBBBLLL -FFFBFFFLRL -BFFFFBBRRR -FFFBFBFLRL -BBFFBBFRRR -FBBFFFFLRR -FFFBBBFLRL -BFFBBBFLLL -BFBBFFBLLL -FFFFFFBLRL -FBFFBFFLLL -FBBBBBBRRR -FBBFFBBRLR -BFFFBBBLLR -BBFBBBBRRR -BFBFBFFLLR -BFBFFBFRLR -FBBBFFFRRR -FFBFBBFRLR -FFFFFBFRLL -FFBFBBBRRR -BFBFFBBLLL -FBBBBBFRLR -FFBBFBBLLL -BFBFFBBLRL -FBBFBFBRRL -BFFBBBBRRL -FBBFFFBLRL -FBBFBFBLLR -FBBFBBBLRR -BFBBBFBRRL -FBBBFBFLLL -BFFFBFFLLR -FBBBFBFLRR -FFBFFBBLRL -BBFBBBBLLR -BFFFBFFLLL -FBFFFFFLRR -BBFBFBBLRL -BFBFBBFRRL -FBFBFFBLRR -BFFFFFFRRL -BFFFFBFRLR -BFBBFBBRLL -BBFFFFFRLL -FFBBFFFLLR -FFFBFFFLRR -FFFBFFBRRR -BBFBFFBLLR -BFFBFFFRLL -FBFBFFBRRL -BFBBBFFLLL -BBFFBFBLRL -FBFBBFFLRR -FBBFBBBRRR -FFFBBFBRLL -FBBFBFBRRR -BFFFBBFLLL -FBBBFFBLRR -BFBFFBBRRR -FFFFFFBRLL -BBFFFBFLRL -BFBFBFBRRR -BFFFBBFRLR -BFBFFFBLRR -FFFBFFBRRL -BBFFFBBRRL -BFBBBFBRLL -BFBFFFBLRL -FFFBFFFLLR -BFFBFFFLRL -BBFBBFBLRR -FBBBFBBRRL -FBBFBFFRLR -FBFFFFFRLR -FBBBBFFRLR -BFBFBBFRLL -BBFBFBFRRR -BFBFBFBRRL -FBBBBBBRLR -BFBFBBFLLR -BFFFBBFRRL -BBBFFFFRLR -BBBFFFBLLR -FBFBBBFLRR -FBFFFBBLRL -FBFFBBBLLR -BFBFBBFLRR -BFBBFBBLRL -BFFFFFBRRL -FFBBFFFRLR -BFFBBFFRLR -BFBFBFBLRL -BFFBFBFRLR -FFBBFFBRRR -BFBBBBBLLL -BBFFFFFRRL -BBFFFFFLRL -FFFBBFFLRL -BFBBFBFRLL -FFFBBBBLLL -FFFFFBFLRL -FFFFBBFLRR -FBFFFBFRRR -BFFBBBBLLL -BBFBBFFRRL -BFFFBBFLLR -FBBBFFFLLL -FFBFFBBRRL -BFBBBFBLRR -BFFBBBFLRL -BFBBBBBRLL -FFFBBBFRLR -FFFFBFFRRL -FFBFBFFLLL -BBFBFFFLRL -BFFFBBFLRR -FFFBFBFRLL -BFBFFBBLRR -FFFBFBBLLR -BBFFFFFRLR -FFBFBFFRRL -FFFFFBBLRL -FBBBFBFRRL -FBBBBFBLLL -FFFFBBBRLR -FBBBBFFLRL -BFBBBBBRRL -BBFFBFBLLR -FBFBFFFLRL -FBFFFBFRRL -FFFBBFBLRL -BFFFFFBLLL -BFFBFBFLLL -FFFFBBFRRL -FFFBFBBRLR -FBFBBBBRRR -FBFFBBBLLL -FFBBBBFRRR -BFFFFBFRLL -BBFBFBBRLR -BFFBBBFLRR -FBBFBFFRRL -FFFFFBFLLL -BBFBFBFLRR -FFBFBBFLRL -BFFBBFBRLR -FFBBBFFRLR -FFFBBFBRLR -FBFBBBBLLR -BFFBBBBLLR -BBFBFBFLRL -BBFFFFFRRR -FFFBFFFRRL -FBBFFBFRRR -BBFFBFFRLL -FFBBFBFRLL -FFFFBFBLLR -BBFFBBFRLL -BFBBBBFLRL -FBFFBFFRLR -BFBFBBFLLL -FFFFBBFLLL -BFBBBBBLRL -FFBFBFBLRR -BFFFFFBRRR -FBFBBBBLRL -FBBFBBFLLR -FBBFFFFRRL -FBFFFBFLLL -FBFFBBBRRL -FFBFFFFRLR -FBBFBBBRLL -FFFFBFBRLR -FFBFBBBRRL -BFFBFBFRRL -FFBFFBFLLL -BFFBFBFLRR -BBFBFFBLRL -BBFFBFFLLR -BFBBBBFLLL -BBFBBFFRRR -BBFFFBBLRR -BFBFFBFRRL -FBBFBFBLRR -BBFBBBFRRR -FFFBBFBLLR -FFFBFFFLLL -FBBBFBFLLR -BFBBFBFLLL -BFBFBFBLLL -BBFFBBFLRR -FFFBFBFLRR -BFFFFFFRLR -BBFBFBBRRR -BBFFFBFRLL -FFFFBBFRLL -FBBFBBFRLL -FBFFFFBRRR -FBFFBBFLLR -BFFBFFBLLR -FFBFFBFLRR -FBFFBFBRLR -FBFBBFFLLL -FBBFFFBRRL -FBFBFBFRRL -FFBFBFBRRR -FBFBFBFLRL -FFFBFBBRLL -FBBBFFFLLR -FFBBBBFRLL -FBFFFBBRLL -BFFBFFBLRR -FBBFBBFLRL -FBFFFBBRRR -FBFFFBBLLR -BFFBFFBRRR -FBBBFBFRRR -FBFFFFFRLL -BBFBBBFRLL -FFFBFFBLLL -FFBFFFFLRR -FBFFFBBRRL -BBFFBFFRLR -FBFBFBBLLL -FBBBBBBLLR -FBFBBFBLLL -BBFBFFFLRR -BFFFFBBRRL -BBFFFBFLRR -FFBFFFBRLL -FFFFBBBLRL -BFBBBFFRLL -BBFBFFFRLL -FBFBBBBLLL -BBFBBFBRLR -BBFFBFBRLR -BFBFFFFLRL -FBBBFBFRLR -FFBFFFBRLR -FBBBBBFLLR -FFBBBFBLLR -BFFBBFBRRL -BBFFBFFRRL -FFFFFFBRRR -FFBBFBBRRR -FBBBBBBRRL -BFFBBFFRRL -FBBFBFBRLR -FBBFFFFRLL -FBBBBBFLLL -FBBFFFBRRR -BFFFFBBLRL -FFFFBFBLLL -FBFBFFFLLL -FBFBBFBLRR -FFFFBFFLRR -FFFBBBFLRR -FBFFBFFLLR -BBFFBFFLLL -FFBFFBFRRL -BFBBFBBRRR -BBFFFBFLLL -FBFFBFBLLL -BFFBFFBRRL -BBFBFFBLRR -FBFBFFFLRR -BFBBFBBLLR -BFFBBFFRRR -FFFFFFBRRL -BBBFFFFLLR -BFBFFBFLLL -FBBBBBFRRL -BFFBBBBRLR -FFBBFBFLRL -FBFBFFBLRL -FFBBBBFRLR -BBFBBFBRRL -FFFFFBFLLR -FBFBFBFLLL -BFBFBFBLLR -FFFBFFFRLL -BFFBBFBLLR -FFBBFBBRLL -FFFBBFBRRL -FBBFFBBLLL -FFFBBBBRLR -FFFBBFBRRR -BBFFBBBRRL -FBBFBFFLRL -FBBBBBFLRR -BBFBFFBRRL -FFFBFBFLLL -FBBBFFFRLL -BFFBFBFLLR -FFBBBBBRRL -BFFBBFFLRR -FBBFBFBRLL -BFFFBFFRRL -BBFFFFBLLR -BBFFBBFRLR -BFFFBBFRRR -FBFBBFBRLR -FFFFFBBRLL -FBBFFFBRLL -BFFFFFBRLL -BFFFBFBLRR -BFFBFFBRLR -FFFFBFBLRL -FFBFFBFLLR -FBBFBFFLLL -BFFBFBFRRR -BBFBBBFLRL -BBBFFFFLRR -BFBBFFFLLR -FBBFFFBRLR -FFFFFBFRRL -FFFBFBBRRL -BBBFFFBLRR -FFBFBBFRRL -FFBBFFBLRR -BBFFBBBLLL -BFBFBBBRRL -BFFFBFBRLL -FFBFBBBRLL -FBFBFBFLRR -FBFFFBBLLL -FBBFFBFLLR -BFFFFBFRRL -FFBBBFFRRL -FFBFBFFLRL -BBFBBBFLLR -FBBFFBFRLR -FBBFFBBRLL -BFBFFFBRLR -BFFFBFFRLL -BBFBFBBRLL -BFFFFFFRLL -FBFBBBFRLL -BFBBFBFLRR -BFBFBBBRLL -BBFBBBFRRL -BFFBBFBRRR -BFBFFBFLLR -FBFBFBFLLR -FFFFFBBRRL -FBFBBBFRLR -FBFFBBFLLL -FFBFBFFRLR -BBFBFBBLLL -FFFFBFFLRL -FBBFBBFLLL -BFBFBBFLRL -FFFFBBFLLR -BFBBFBBRRL -FBBBFFBRRL -FBBBBFFRLL \ No newline at end of file diff --git a/2020/day-5.ts b/2020/day-5.ts deleted file mode 100644 index 302f174..0000000 --- a/2020/day-5.ts +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -const rl = createInterface(createReadStream(`${basename(process.argv[1], extname(process.argv[1]))}.input`)); - -const seats = Array(1024); - -rl.on('line', line => { - const row = parseInt(line.slice(0, 7).replace(/F/g, '0').replace(/B/g, '1'), 2); - const col = parseInt(line.slice(7, 10).replace(/L/g, '0').replace(/R/g, '1'), 2); - const id = row * 8 + col; - seats[id] = 1 -}); -rl.on('close', () => { - for (let i = 1; i < seats.length; i++) { - if (!seats[i] && seats[i - 1] && seats[i + 1]) { - console.log(`Seat with id ${i} is free`); - } - } -}); \ No newline at end of file diff --git a/2020/day-6-example.input b/2020/day-6-example.input deleted file mode 100644 index 8fdfebd..0000000 --- a/2020/day-6-example.input +++ /dev/null @@ -1,15 +0,0 @@ -abc - -a -b -c - -ab -ac - -a -a -a -a - -b \ No newline at end of file diff --git a/2020/day-6.input b/2020/day-6.input deleted file mode 100644 index bff417e..0000000 --- a/2020/day-6.input +++ /dev/null @@ -1,2087 +0,0 @@ -v -vx -v -vx -nclmbv - -odgpnwqxhbits -pqwsnxihogdbt -pogiwxdhqbsnt - -q -o - -apulnqresohvktxcymzibdwg -sigdvakmlyxhetopnubwzrqc -iushndtclbeyowxpqmkgzavr - -ow -wo - -phegq -eqgph -hgpque - -xispjzq -sqkzcupi -ikspqyzue - -hgfesyvn -dnsvtkhglea -heygnqbcvs - -qmrpy -pmrck -vcprum -mrkcp -mrp - -kgjx -jghk -kjgu -enlgdwzqkjr -vjgk - -ungsdozkphlxy -nbkgzaifsovjpdt -geoskuyznpcd - -qw -qw - -x -r -sl -v -s - -kxcn -kxn -wxtkn -xkcn -xkn - -peionmzqyda -apdinomqzey -npmqoiedzay -dmpzoyqiane - -gpaedw -mwda -daw -awbd - -fyxeptlrmisjhdzquv -xfqydzruvmjepsilth -sipulvdzmftqeyhrxj - -kzofrcamenxyvwgpq -zqkrapxwomvycgnef -ywxvpazgcenrqkfmo -kgcvezmfqwrpnxaoy - -zhf -zegfhd -fhz -hfz - -iqspn -bytmd -sq -gwx - -begosk -gnbskz -sgkb - -ok -ek -ek -k - -hbucsatqvdryfojxlz -tufzxjvbrwasemg - -d -ef -k - -p -mrp - -kuywroetvjnf -wjvtkreufyn -frkyjwevntu -frtewnkjvuy - -iu -wzi -axbcgpldyi -seoiz - -ekjmbsuwglftpvya -esmwuftgpvyjalkb -vflbtyekmjupasgw -tepmwgksulybavjf -psawvbtgjfelmyuk - -jsmoydnvkiql -lqdojsvnik - -ayrtxivjlpeuzohnk -whjitnkfyealoguxprzc -bzjiruohtlakxnedypm -pmyxeizqjhkntoarul - -vnrcwouidfb -bufrwnociv -unrvefbcwo -cvnswubfro - -hmnoazwvtcrigqsujldpk -qeflzdwyongvtjishpacumr - -ytwpgkvceaolhrz -agyepkhwlzvctr -yvpkwcgerzhtaq -pcaeygktzwhrv -rgvpkwtylzhcea - -io -oi -io -ito - -ckmfawyb -glvfiymobadc -jnsfbmapcy -jfysmathnbc - -uxbfdygqwpom -sxmuwbdporyvqh -rbuqmwxydpo -ncpuyowqildjxebmk -wxuysoqhvbampd - -keo -oz -jdorxbia -lo -ok - -zk -zco - -bhwmscnrqeou -rlqenzswohbmu - -synmfzljkdebq -cmdyzlfekjbns -nkgzsmvlydpjobfute -lsfjkmnzdeby - -xshlzwcndtjefi -wcnljfditsexzh -ehtsjwidflcznx - -zry -vyqz - -owfcybsdipnqlthavu -psdiqfhwctrzvaybon -ybmpdciqhvtsfawon -givjcetkhwbdyponfsaq -cvotsnhqfywplidab - -cibwptjnu -ncruhi -hnuic - -apzjqbdlwyicfgxv -apxodvwlzyfbgqcij -pcdxjvzwqfliyagb -rixjaclsdpvyzgwqmbfe - -timpsox -poxsm - -fres -refs -fersq - -w -z -r -w -r - -xz -x -x -x - -ciyhkpjswqvxz -xyskvphmowjzcia -kywsxihpc -wtpnflcsekhbgxud - -qrtweigjlbucfxnkos -iwlbgmnosuxfetkrqc -sfbwxcotierqukldn -euroqfdxywclsitkbn -qelfbarchnwuxtsiok - -gj -woh -g -jr - -lpcdqf -qdfupwzcl -dpcqgtl - -zlnkeyroq -rtyoleqnkz -leykztqnor -ahoukcelrxjqynpz - -twxjdbuhclzgnop -fgeqkcbvziwtludop - -ylukhwtcf -aikdrxfov - -ucbklojiyxmz -ulkjco -kroljuch - -rfhyj -fhy - -cmtedvxioy -infmacweshtuo -tpoimecz - -kylduhw -yublkhd -kdulyh -dyuhlrk -zhfgkudly - -laoemdcgpyhtnb -ygclebodtmpnha -zomgnqpalhebxwtcd - -bmogrnztvyil -vlotrzngbmiy -lvyogrzbimtn - -zjcgheblotdramsn -mlgbshrzotcnjawd -otgsjdnmbrchlza -dbazlpfkhgtmsvocnjqr -sgrazcjondmlhbt - -ryhifaxpemsgcdubvtjzwnol -bduiojqhcsvlyrxefntpgwma -pvebfwitculrgyjshkdxmaon - -lqmopgwbesjhk -mgbkhqejlswop -wqklaeogsdxhfbmjp -sjgphokmqewlb -kesrghbmpjlowq - -tu -rp -r -rgh - -tfeyhjbnpaqwz -rxuefvgiaybzqth - -pwx -lk -iahyv -jr -p - -ezsghqtdnjbfox -dsucq -sduqp -cusvdqy -dslwqm - -dm -gf -g -xtg - -mfihn -mhyifot - -iabeswqrzlcxvkpmtnug -qexctgrkwbpusazinmv -riztmgqsewunxbapkcvj -avbuxqizmrkeswtpncg - -ozrwipdmgajlkfuxcnhtyveqs -fntcigalzdxmyuesjkqwo -dtfyeqklgjmwxunosizca -efclkowaujqzigbtymdxsn - -jkiupmatwxqhdrs -midjhwutq -dmhujzqwyit -dwuqhymtji - -ziqfh -hnboqe -qhktzdfp - -qohbywgtlucajf -ltahuywfjbmc - -arfpqdcbtnw -kfzonycewxbghvr - -tdxqelwnu -luenxdtqw -udlteqxnw -wxendqlut - -pvkrgaushqidfmnjz -eajzrkhndfitsqvmwugyp -sgohxqcvrzunapjfdmki -vinodpkazgfrmcushjq -jmufirnszpdqoahgkv - -uvcmgfrk -fugmrvck -kfuvrmcg -cmrfgkuv -kcvumfgr - -kmrb -krbm -rkb -bekrt -rbmk - -mzbrfsnxgjpywavcohuqlkitde -xpekistdzlrgmcawnvuqfohjby - -vrjew -rvj - -qlefnd -fdleo -pxcehwdfy - -amftbpvo - -ljcyn -cynosjum -jync -yrqbwjzc -jcy - -tmdcuk -ckudm -mucdk -cdkum - -icsvhmefaztoxkgndq -sbyqivkrdplwjemou - -jtrhafpkbwzdox -hbrwpzajokfx -jbkfaphxzcrwon - -bqg -qgb -bgq -qbg -qgb - -ljte -jle - -tvhjx -hvjwxrt -vtjxh -dtjvhx -vjxht - -zsdejcrvab -kbjzrscaedv - -oehivmku -igfhuxozy - -x -xs -x -x -x - -klqnrzftv -iqgfaupt -fdqgswyjt - -opjeslcx -psohecjxl -yxelsjoc -lescojvx -molnextcsj - -sf -cps -fos - -crxbjzkivydsgfpehmq -wnhfgljeptzrmikcy - -bghydvqxicsfunlzpart -rsyugqcxtvdzanpblihf - -v -gnvw -lv -v -lv - -mpzvdjqhxnuocr -chidrnuvxmkjqpt -suhdxgvbcnrpmj - -ewpfugobznrqydsj -ivgxtjludcm - -enytuvzoqmljfwd -satbgwcrndzyk - -fuzl -ful -lu -lpuxy - -qrhltkesazpmo -puaedmzsqhot - -vcktz -zqtjsbuiaomwf -ygzkthx - -zt -tdz - -fvpjlcarqdukio -luotiqzkjfrwahcdvm -rcykufoadqxilvj - -kfpuwxi -wpfxuik - -xjzpf -cyqsouwf -xzf -zf -bifpj - -q -cw -n -nu -q - -lscdtzvhajkqpm -vdpklhqscm -pvcdqskljh -hcjdqklsyvp -eqshcdklvp - -muyldxobakfq -ecjvfm - -jkas -ws -s -ws - -qbjzcolnuy -jyulobzncq -izqlnycoubj - -yvsoztedn -eotvydz -yzetodv -edvoyczt - -tcfqkxrib -fozbtnlwucq -qvagfdebtc -qcpftbk - -amlcyk -acempy -aymcv -cayml - -gsybwf -ybsfgw -bsgywf -bfwygs -fsygbw - -hypxicwobt -pciytbxwh -xhycspitbw -pcibytrhxw -yckhxtebwpi - -olneqtcpzfiahbj -oitbqejcahpnfmzl -bpnjyhfkqmlczteoai -hlpjefoaqznbtci -jdwtzsfcviaqnobhpxel - -mkflqourwyh -kqmylohfu -lyohqumfk -fyhukomplq - -cfegzaprw -prvbgiymj - -besuka -hsnkua -slaguxky - -smwuovdpnjfyl -mcjvguors -qjvsmiou -abotmkxujvs -uhmoqsvje - -udrmcxqay -dqyhumca -mfwcujskglbedqt - -xewpyrsjzktgbaochuni -xjaohuwligysztekpnc -tfghodxyjsnapmquwcziekv - -fxypwlo -wpsxleyfo -ylmpxfzwo - -ok -rspbkt -mauyxcw -rqdkz - -fsehripoyjawt -styheviwfrn - -onxrvplyuzqcj -vlzuyrcpxoqjn -nuoqyrzjcpvxl -ljyuoqvnzprcx - -o -ac -c -c - -hwxmesjuzo -hylvoxzpfbntsr -shoquzx - -pidfxg -igrxm - -gshkfbcujpyztoevxdlmaw -kzvmejbygdpaxufhlcotws -hfgamkstbwjoyxlczupevd - -p -p -ltf - -iufdzosnagkhtw -dzkhlgvsitucoa -adtgzokhsviuc - -jywe -wy -yw -wzy -yw - -ghvadykiscnfxo -noxckgivyhdaf -gfxmtodbwvnkhipaqy - -ifsp -xnivluaq -fioe -wisydc -siw - -jxbmclnevwztqug -keptqcrmzufglhi -tleqgyvjbumzdc -xzdmslqcutge - -ogdxpnjbti -ipgnotx -ipehgonkcxrtfa -ntdiygpox - -wxhcjtredknifvulymp -vgksmwqzctybidjofha - -lxmficysbt -jslmrn - -pcoxigrdtkul -sjmhtbxulyord -uxlcpdktoarv - -crgundohktjfasebzvxl -gdsvcufrnljazotkxehb -onbgcjfeirxkhzvudtsla -njcheafbokgzvsxrudlt -ekgvfruchstjldoxzabn - -wmkivpgfqdrsl -wmcjvofkhnz -kfwbuvam -jtmwhfkvz - -thy -hy -yhe -yh -dqbyh - -xtbhkovsjcga -xqkoeavjsch -xacvkjhds -mcjuwskavnrixyh - -lhfwqr -ypkruwqs -xcgdwmj - -eyiwrundqsflgcavxk -fejmwtyulodkhrzbp - -yvz -expa - -aohj -ejoai -ldypfnejoa -dcxpjoatv - -vuinj -prv -v -vlr - -sqpdmrnlwa -nlgasrpqomd -padlqsmrn - -r -pjd -d -azbhs - -hfotieypnlwdkjzv -jlfveimtdckongwzpy - -af -zaf -afn -abf - -csjx -scrk -ucws -csj -sjc - -juwtder -dtjrwe -werjdt -djreywut -rceoqjwdt - -nazufjeomxpkc -xmeopajcunkzf -pfcuazejknmxo -nkzceomfapxju - -epiykxforjz -fylzbxjeoipg -ahfyxvpmsujiedzon -eoyxcqwpikjzfg - -umfrlqhakzdn -mshjfdkqungrzv - -opxjdgemsvailruzfbcq -ozmgbdirxelyfsqpjvuc -iqbucpflxsvzdoetjrm -ysiqolmberzvjnctdxgufp -bxfemdhcukplzrijsqvo - -yocg -g -uqg -rzy -vjbmw - -vljzumo -ujzvmo -vujomz -vjzomu -zmjuov - -srwagukx -ahjroqmxy - -cgkj -jcgknvs -jgkyc -kcjgy -jrgck - -ugcwvx -gfuzaxw - -n -o -n -n -n - -vsmd -mcdvbs -cdmxy -tadr - -znsokugwejfylica -iwpnfyolqzkcuaegdsj - -azuver -remzau -arezu -zerau - -wevbmlq -bwalcodevx -ewtuxlbv -zivypeswlb -ebwvaln - -qjrdgxmc -hrcozqdxj - -mpcogjzyrhisuxlv -mskpazxdfvqc - -xtzyl -lxyt -xytl -xlyt -oxslyt - -jrteqswkcazlbfhog -tsqafcbgrelzokhjw - -fjqlibpwukcoznavyrtd -bzdtupklrqivanwyojfc -lvjarpkyubndzqiwoftc -bdrcniwvktylpajoqzuf -uycprvalqdiwonbjztkf - -lwga -dgswz -zgwy -nwugcrik -gwsy - -gwmvxakicou -avugcmowixk -ckxugomwvia -ukwacxogmiv -xiwavcgmkou - -znvgeymhb -rztconyiq -lwzayn -jswnuzyk -fnwuxlypz - -etkdwlgscmzyuafvhbo -vhctfgkmwouaylesbzd -vfcetldzsyobghmuwka -tsgzmkufeajlvwcyodbh -gazdhmkotswlfuvbcey - -zdsjweg -sezjgd -dsgzei - -zi -z - -tbg -fbtg - -g -g -g -g - -rid -jvi -inxo -id - -dbrjtfupcyvzlqmwei -zqbwfmljvcdirtyepu - -jmhubvclsdprw -cpswbmldjrveu -rpbsvucmdfjlw - -qk -ekniz - -kvlmhegzcryd -zrlmdgvefyhc -zhgvrqueymdca -remdfyhzcgv - -zxhiaqs -hxiqsa - -sumrbd -qgrbuw -ubqgr - -dkmqsebjznylwucxot -ewyqhjrlpcfotbis - -ti -kxi - -dvgmlyepfnhscui -isbvmudynplf -nzqldwmfyuvtpi -finlydpourvme -dulnypvsrafmik - -zemctnsralu -trnaelzmsuc -azrstumnecl -mltrceasnuz -rtazlucenms - -aydgxnwehomujpv -nedjuaxhopwvmg -dvgwhfojpanmuxe -wjaenpdvmohugx -vanuomdxjehgwp - -xchjblnwmogv -coxlngbwjmhv -mjbwoclgxvnh - -br -rohb - -knpclsvozb -slcvbznk -klcbnvzs -lsvbkncz - -cehpgtzmawkjndufrlixb -anrtxfdbhiwmcjzplkeug -rkmwtcunzxhjpgbafdeil - -rqlstcwxkmoz -thsvxzkueymrlqw -rqlskomwzpaxt -wcxrzmptqkls - -tshv -hfzdlpij -hmces - -kfjmaedcoqltuwp -jrngliqdohsce -bgclzdhjqxyero - -urndaqxz -fyw -wzqua -ehglomjvbk - -guhfvqlnkydpiz -ljgyoiqarzksuwet - -yutebcorzh -slxcdkqnhjga - -fivxqukh -kixqzvu -vqxuki -xnpiuqvk -kvqfxudie - -rpsfdkmc -cdefrksmp -khmsfrdpc -pdmkrcfs - -hwn -whn - -rxhbzyedclofgwmuktsp -xlmozsbgkcfeyurthdw -psgtkcfazdwomblhyerxu -ytvfsxukgwmlrzdhobec - -nrvyx -vytxn -xyvn -nxvy -xnyv - -qct -cqt -tcq - -y -dy -lcwtunshbmy -fy -ry - -cnboedgyxatrk -ktdbeocgnay -wbkgtecnyahmodq -nxbtgzcsyeukrado -ydagcekbfont - -jytulh -yhtlz -fwtrkhly -bylht - -huigqrok -ikhrong -bighkwor -kgxrhosi - -zbkrpelxtsohdaw -ewzkvcxrdtboas -rabkdwoxyneszt -axhkbzrwdteos -rtbowkelsxzad - -aonplewqryh -euyqrfncsovkld -byalnwiezroq -enobxrlqy -pmgzeryonql - -akxpsmecuj -kfgsexjm -oxqfeskjm -yervixmdktlshbj - -r -r -r -r -r - -rdghefnubpzkma -dhubafromtpekzgn -knmhfjduebpgraz -zpekdbfamrnihug - -ybcgsmlwhovidfezp -omfpzqugycwrhbs - -x -x - -vjahspyncxzmie -zmpu -krpmzog -tfpmkz - -morafxw -xyckafoqwjm -ialpowmf -xhrsmwokbfjazu -anmfowdbq - -gdpblscxazjrmikoyth -exrolqfahdbymcwpksjt -gtmadncysrlhpojvxkib - -nxdilkwregfbaoqp -exnjrbsifwypkqovag -fgrotinqbwpkxae -flndzeoxkwgrcptibqa - -sidjln -mjslodni -ztdoxjnise -odnsehfjti -dnsyij - -qx -wmxtj -wxzmtucqy -godkvenhxpb -xrztj - -xofhvkjytqus -ytdqjkufimvx -uwyqntcvfpxkj - -rdtqukinob -wzufpcolmskynvteh - -vnab -kouvrfe -ljvcd -wqbdpvsy -bighvnmx - -frgsavwjel -fjlrwsaveg -afeljgrwsv -jlvsrewafg -kvfesjlwgra - -ygdszflehmwcnbopiatxju -jdnupgzmilsywaechoft - -da -rzfvailh -bhorq -ctgujpmsw - -ymbnzldsi -ltvsfm -mgcsl -emslgw - -taqecxvdypifblzgk -cekxfvgplrnqbty -vejogtfwqbyknlrpxc - -souwzdkcbqf -awzqgvbscukdpxn -bcszjdfkuimwq -sdbcuzqkw - -avrlf -kerlgmuahvc -wavfibznrol - -upnkam -xmjt -milex - -rxotufwczkpvia -pajkvhwtme -gpnektwljasv -pknaqwtvey -wpadktnlvjb - -kpfj -syurwad -asyvld - -p -bpz -po - -s -u -s - -ksvbeno -uyfivq -kbjodvh -czptrmawg - -xtiqze -xtisdz - -pylbdvkncjurmgh -yhbdoltvrpiknmjucg -vbmlhynrcugjpdk - -byoavnixtlzepjds -sapxunqeizdvblyho -qvlmeoisanzyhdxpb - -ifykcw -iyckw - -u -p -s -s - -f -f -f -f - -fvbjxaiklos -ufqnvcgxikdpalobt -bixlarfkvo - -ygpsxce -cpdsfygaxueb -ycgsxep -epcxsgty -pctxesgy - -meawzoqnidgh -hodmagqnzew -mwhzndaqgjoe -cdhseoqauwngzmx -oawmeqfdnhzg - -yrlvejxocsh -hvjrsmloyne -nsrvyojlhe - -zhufxvrkcdmwqlsa -lergvwdqnaosxtzchukbj - -xbvyt -ybvndgxt -gzxtonyb -xbcuwtyp - -creoxajkgvq -vgljkrexacwmhq - -wckjovuftgmb -boktfjuvgmwc - -cguaojyvre -ohiknuqags -lcazjyguor - -inhyfk -kify - -uhtqci -tfoqacim -srvcjytkqgx -hqctz -qmctahizn - -vekplqxuhrm -kmeuprlvqxh -vhlrkmpxuqe - -at -tagexyi -mpt -yxta - -uezmyjqvbgspirlc -fydbljgwmzxquecop -zptrgeybcqmluj -pelzjcugymtbvq - -fakguojpbsic -ubcfgyjakpiso -bliusctfvkampjog -fybsicjawkupog - -kmxerqlautij -zxidayte - -imbngcehtvs -oipfmkrqusnwxdzyl -imasjvn - -pek -e -ei -ep -ex - -yuw -uyw -wdysu - -omikta -zjvatmw -txsma -cm -lndgqmry - -cwazbkolvys -liyoveacbswj -siwokbavleyc -rocsyndufablvwx -aylbvcojesw - -nazfjsrouhgtv -zgsprothnufav - -ptmshxwqk -sebqodwi -euqsw -zwousq - -uqltjsikhpvefdawycbzg -plyhvtieubakzswqcfjgd -wehjvikyfpcsgaqtlbuzd -sfibzvquyljekgthpwcda -cgbtvdolizaeqypfksxjuhw - -izeqstg -sgiqzet - -fqbmpoxscydhrtljzga -cfqodxevmajhbrplzt -oecfrzvbpdaqhtjlxm -adfbxrmqlctzpjho - -dsmewbhpvrfuknj -opcvhwtrqkue -rwvkguhpzoe -vxpghreuiwqk - -fjzi -ftmizn - -xumjz -ujxymg -zumjx -ujmx - -n -l -l -x - -ghwfslriojz -rfzliwoe -flrziobw -ifcpozlrw - -smvfnglxaeczqwukojhbi -uieagsoqbhvlmjcfxwknz -nxoacfwemhijsgqvzbkul -qanmsiwvflcjbxzoeugkh - -pzciwneljbghoufdvymtqar -exlhrjvkpnmdoqbtzusiwcgf - -uxjwpobgcflndqairke -oktwumrzjlyedagxbinsfp - -oibhmyeguqkxjrcpawzfvds -vhsauyxdrobwcjmkzqepgif -gxhiwozfkbsecamrypudvjq -mxywofehvsczapkbuidqjgr -xsmvybwqdgrzeucfahpojik - -gdtlkuomn -ytkueoglh - -xgimja -gjxibma -mjbagix -xaiojmg -mgjaxi - -sgnfdiz -dto - -yhkvqrzw -hyknjrzvq -xtrhdsvkzoqy -ykqvzhr -zkqyhanegrv - -tzqrhavysuodmjp -abvpofyzhmrjqdt -yzopriuqnvmtahjd -atmryjpzhovqgd - -cyljrwofasq -afoqswrjclu -carljswfkoq -ljwsfocqyra -xjolqcwfars - -r -o -ak -xdje - -lfyjxpoeau -yhlgcftszpr -pkylfomw - -lunijqekwg -vafgdsjqeklniw -yeglwqkjin -leqgjkniyw - -mpvlijnfbz -jzmfbplnvih -jqdlpvbmnzif - -tk -tk -qkst -kt -tk - -mdowpcnxgbvuytqezljsk -tbnzcduipewvxlkqrsmjyga - -ilumzjpqotcv -fgtmowyx -gdsotkrm - -yncslevbgrqmizwu -brclynqgzvuewisfm -lgbzcesuvqnrwmyi - -bjmzopcdiqlyueh -olyupebiqcmzjhd - -eubsjrvwmyinzkaqdgcf -icqzjksbyregauvfdwnm -jugdnbsczwqfarvkyiem -benyrimfwzaqvukdscjg -ndcuvaziekbwyjrqgsfm - -g -c -c - -gvyfqupnxtswb -uvtykbjxgifcqz -lhvobuxgqfetmy - -dpzgaulb -plqugbrdmac - -htr -kgrt -rt -tr -trg - -o -qv -lr -m -l - -qotxnerijpfbkcagylh -nilhcfrpkjgboxaqey -ognqxipefrbjhlkacy -kojtilqxyrhbpancgfe -qjilgekcfsnhxapomrby - -fes -feoijn -ef -ef -ef - -dlzga -tlsidg -gdl -lpdgh - -onysxwkqlcgdemhup -mzlscwgkdnouexyp -kzdubeoyslgnpcxm -dymulpowksnegxc -kpusvxldgyaonemrci - -xh -e - -utbirhymae -yzehmoukq - -ijvulcmbrgkyxao -uvrajglcbomkxiy - -xo -zo -o -xo -o - -mbghatcenlifqjdkp -ejscikpgvtomhnxqzf - -stpvo -cjvpthsl -spvdnyrt -qvypftsx - -obrxaqyudvinmk -qlimnvosubahydgkecrx -yrftzoxkjqvbaidm -kvqaxdmboirwy - -dxj -xdj -jxd -jxd -djx - -hfjeucmkrvnwxs -nxujekrqmsbofhc - -ezarol -lebz -bzel - -jgmzcl -jlzcmg -cmlzjg -jmclzg -gmcjzl - -o -u - -bdfqljiuacptzvgrxoe -pauvztlihdqrjofgx -xtrjvzuaipfldgoq -jzrdtxqlwiavungfpo - -cjurgpeyvlzhafx -aurhsfbvpeyxgjzc -gzvhejlkpxyfocura - -rvyfbicazduolwtgqk -qklnrgyaofdzvciwut - -qsw -qs - -nrfgxpujobhk -rxmpnokdgbjfi -lxbngkrfyjvcoz - -e -e -zegkx -e -e - -kon -k -k - -ekvi -iekv -ekvi -ivek - -jfbyxwhrne -nxjhrfbdwy -bewhryfjtnx -mfhoxyjbrsnw - -bn -n -sxv -d - -egrzknhbxfvqtdcu -edhrioxvjgnzbf - -yjoskmhw -kdtqfehazbyu - -zq -zq -qz -uqz - -ilbpcz -ibcqplz -gczbpil - -nikychwgab -caibgwklndy -ckbenqwuafyg - -qubikjdz -jkiuzdb - -gwmavrpfsdnkyizuelt -yuqnvjmlogpizcfetx - -tnsf -thnfs -tfsn -sntf -nstf - -vflagunhs -aiwvlhjfsunxg -ulvhgfsna - -yajtfdwh -hzdpalftjb - -nazpqismug -pznuismgq -mgiqnupwsz -mgptzusniq -boifzpmsuqgn - -ohu -ht -hpygo -ijkdfhcb -uhno - -kfzmrhyjvw -hzgxpjbkwvyr -zykmfrvwshj - -yqsezgcojbw -zjsgcoeqby -jgfsbozqyec -czsgoyfbjqe - -fjywktd -yjktfwd - -nwvrodtpqy -xtrvnosihzgq - -gdwcmlxiqtynsjozapeur -xwlgsjatqzycnodprmue -adxtgqujrcopnlwsmezy - -snep -shwz - -unvpgc -guncvp - -suctpbxogra -kcxvgteayu -ztgxuacy - -pewbhlvjtg -omskldnz -iafryucxq - -zoucjefxpdta -xbfijrelpucsot -ktoexjpcauf -jtezoxkpfhcduw - -xiaszncr -asxnircz -xzncrsai -rixseuzanc -nzaicrsx - -owtvxqcizrapl -alqxivcprzowt - -ltrhdykufvwex -ekxvfldwuhrt -ervktduwlhfjax - -ylvgpjthiex -snmbgjfzduxqearikc - -eml -bkhyl -rzsoitwqn -dacupjev -fldc - -uqigoj -ojui - -zgbsumeycaxvontwdkij -jbtelqcxnumsoakiwyvg -waseyvijugnkobptcmx -atesbkmjuhcvfngxywoi - -pc -pc -ikyp - -xtgvlenosarwubmfihz -txganvweourhbqslfmiz -lientrsuwghobfmvxaz -taluorneizhswmbxgvf -zginuholscexmftrbwva - -xjkv -xtouw -tywx -oxwt - -zk -cz -bz - -qcp -qpc - -ogptyeunzsqmarjc -jrvlopzynes -xoszpnjryle -zbrnypsoej - -nuigyflbxs -yxunspgj -vnuscztymqowgxr -ixnyshgu - -pdn -cyskxdp - -ewlkgbdxqtiz -eqgxitldbzkw -kbdexzgitwql - -c -p -t -v -gqh - -uvigbjqk -ibvugq -vbuiqg - -wzdca -dzawc -cawzyd - -mfaigwlu -pygxjmufwal -ugfwlam -glmafuw - -bewfkxsvl -yxdqnmaturov - -fdrbt -mxjnfdqpc -wdltfo -adwletfr - -t -pgo -e -tiabc - -zbthk -zbkhatr -zbhtk - -flxwhbzkei -lwkhxfezbi -xelfwbzhik -bhzefxkliw -klizhwbfxe - -btmwkoqs -bstomkqw -wskomtbqi -kswtbmqo -kqbswotm - -kdfbzj -bfdzjm - -bf -ef -f -fut -bf - -bvl -lvu - -kezwynmfrgahlbqsjtdxiovpu -wmaukoqsldvheztxrgjpifbny -qgkrwvaiznhpmtlxjubesdoyf -osverdamnxjufcybpkztqighwl - -nza -anz - -wfjsdaq -iwlrou -ykwftq - -zgtuvqxmljwyaifcbp -pcgytlqjvbaxwzimf -cmqzwaljvbufyigptx -sxgvcbweymiflqajtkpz -fhgmjpwclzibtvaqxy - -rohqjmnvlsdaigywbxe -xmhiarjdogqwbvnlsey - -jhz -jhz -jzh - -oemyvhgznpblsq -hpsvzycebqlmng -elhnwqdpbsgzyvm -cenomgyzhqlsbvp - -gdnc -wncd - -tnlprwbcsaygzqxuoev -rxqdasecgwbzmfvntpl - -jtucglizkohrafs -ebjhogu -hdugoj - -ncyvqk -oulfaxqnerid -ptmsynbvkwq - -mxihwyzetlbnkpfs -ksqwhxtzbenfpim -nqbtxwsepfmkih -khixywsmbnetpfl -peikctmafswhnbx - -phylqxrdtg -yxtapqni -nkiwytuveqxp - -lhqrfys -sqdfly -ysfhlq -sylfq - -sqpjuobilhmtvrxaz -kuwgncfdv - -dqzke -qezkd -kqezd -zkqed -kdqez - -lio -iol -loi -lio -oil - -hvpwi -rhvp -fpysmvd -tpvrl -vph - -idjeoxvyqaufgpnlc -xnplcqjvdyigsaef - -y -qw - -rhb -fpqsiadrjkl - -hinvdck -kvcahnid -fhcupntkvdqijmy -dvnchik -aivcnhxkd - -xqugmnktofslbpevzd -yaqztjnicrwd - -biadvoeznswx -iaxszcdwboj -isbdkxzwoanve -gikqxzorsadfwb -asozrwidqxvb - -bvotgwrxe -xbhryeov -ojrvxebi -vxeorb - -fb -rqwl -qlrjyfp -nkhgmov - -zexjvfbwro -wzvxorfjbe -vorwzexbjtf -xeovwfjbzr - -owfmx -uxomf -mfo -cfkmo - -atwsbvcn -mijkzngueoy - -twqprciyaxkb -barckwiptqyx -iabyqwtcrkxp -rqbkipctxywa - -vmhzjek -tx -aix -dsa - -byzxqpgureth -gbxryhptqiezuc -lqrzjwythegxubp -hqruytzegbxp -tepughsrqzybx - -hwydxbeflai -yhewcfbaixd -yhwadxfeib - -hi -h -h -h - -mhket -mtkh - -loacixzmfy -fmxlzaoyci -ylifaxopczm -czyafoxmli - -ymrfxiwbse -ihpqjuaczd - -ealixkwz -gocmqyfthp - -gedjwnt -wtdezgn -hgcuwrtnped -zjngtdlexw - -jk -jk -kj -jk -jk - -gkxldasfhqncbiyu -hnpfbycsgqkuldex -hquxfksigydlcnab -cxauqgdiyfbnkshl - -niahryvlxbekt -dyhknvbaleirtx -tknljyvrihbzxe -seyxknvihrcbtl -bxrhukldytvneiw - -vuq -cfawvlt -rhnvzu - -wxlhvnmispbot -whvbcxmolntips -snhtmbpwifulxov -itswhupmncvolbx -rhtlsdpiwonbkqvxm - -ojmyc -kfzuehvirps - -mk -km -km - -fjyx -jitrevpfy -yjs -jyxmiect -dykgjnzbl - -rbwpjflnoegkqt -hwxceyimsdzntvu - -golf -fzgol -dlxfomg -lfozg -floag - -dfbmcyi -yvzpkrbc -icybu - -mcbditlrfgeaoh -camdhrfbvoglei -riagefbmclvokqz -dbfogjmeacrpl -lwuogecanfxsbrmy - -lgsnwuockhmpxibedqzaf -cvmiepdsubkgwzhf -bsvipdjwcfkmezugh -wgfzicsmubpdkeh - -iyeorgvpmutnhqcwxj -jqoguadpnmrk -nmpquzglaorsj - -apjqhruongvztmiywecl -padwbieyshonfrtxqcukzglv -yolrhezqicgpmvtaunw -mljzahrwcpqygvonuite - -szhjetf -sdtozreuhmfp - -f -f -mf -f - -gnjqcad -idlhjay -rejbwamoud -danxj -zjkdia - -lupiwyqntjgekvsr -gwqupjykitrlnsbo - -ojcxmuqsrhyv -lgcovdyhnifsp - -wphvcu -lznsm - -wpq -qpw -wqp -pwq -fqwhp - -nyzx -ubpx -xwi -wtxhe - -vkujyxtido -tvouidyjxk -vidkjuoxty -uxtoivdkjy -yvukijdoxt - -fpuboyiwdktvc -hsqnzuagr - -swabt -mwsb -sbwm -bws - -idlshcnf -ficnd -tdfcin -nicdf - -ajodwgmsy -wmjvoygd -ojdwmyg -dovgwjmy - -yemtzisjpxchanuovwdkr -evxtomkyhrupwsnizac -ytevcsimkwrnzoauhpx - -whley -dhyetlqf - -fqx -xf -bfxz - -ipwvb -vdnb -rcvnf -chvr -xjtvyez - -sdpuoewx -wfqrphkdelosbvgyum -pudzioesnw -idatsupewo - -knfheau -kanehuf -unekfa -klcsnemaufy - -yhuvigcrp -rivgypcuh -urphgvciy -iyhrcvupg -vuphryicg - -flozkyvhnwxr -fvpsybhlwrz -hzqvmfgrl -irholckaveszf - -gypwufz -agspwqmuyz -yogwpzu - -c -oc \ No newline at end of file diff --git a/2020/day-6.ts b/2020/day-6.ts deleted file mode 100644 index a2cd5fc..0000000 --- a/2020/day-6.ts +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -const rl = createInterface(createReadStream(`${basename(process.argv[1], extname(process.argv[1]))}.input`)); - -const ALL = Array.from('abcdefghijklmnopqrstuvwxyz'); - -let resultPart1 = 0; -let resultPart2 = 0; -let currentPart1 = new Set(); -let currentPart2 = new Set(ALL); - -rl.on('line', line => { - if (line.trim()) { - // More answers for the current group - Array.from(line).forEach(answer => currentPart1.add(answer)); - for (const answer of currentPart2.values()) { - if (line.indexOf(answer) === -1) { - currentPart2.delete(answer); - } - } - } else { - // Group change, count and add - resultPart1 += currentPart1.size; - currentPart1.clear(); - resultPart2 += currentPart2.size; - ALL.forEach(answer => currentPart2.add(answer)); - } -}); -rl.on('close', () => { - resultPart1 += currentPart1.size; - resultPart2 += currentPart2.size; - - console.log(`Got in total part1 ${resultPart1} part2 ${resultPart2}`); -}); \ No newline at end of file diff --git a/2020/day-7-example-2.input b/2020/day-7-example-2.input deleted file mode 100644 index 38b2f50..0000000 --- a/2020/day-7-example-2.input +++ /dev/null @@ -1,7 +0,0 @@ -shiny gold bags contain 2 dark red bags. -dark red bags contain 2 dark orange bags. -dark orange bags contain 2 dark yellow bags. -dark yellow bags contain 2 dark green bags. -dark green bags contain 2 dark blue bags. -dark blue bags contain 2 dark violet bags. -dark violet bags contain no other bags. \ No newline at end of file diff --git a/2020/day-7-example.input b/2020/day-7-example.input deleted file mode 100644 index e7ba02e..0000000 --- a/2020/day-7-example.input +++ /dev/null @@ -1,9 +0,0 @@ -light red bags contain 1 bright white bag, 2 muted yellow bags. -dark orange bags contain 3 bright white bags, 4 muted yellow bags. -bright white bags contain 1 shiny gold bag. -muted yellow bags contain 2 shiny gold bags, 9 faded blue bags. -shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags. -dark olive bags contain 3 faded blue bags, 4 dotted black bags. -vibrant plum bags contain 5 faded blue bags, 6 dotted black bags. -faded blue bags contain no other bags. -dotted black bags contain no other bags. \ No newline at end of file diff --git a/2020/day-7.input b/2020/day-7.input deleted file mode 100644 index 52aecd5..0000000 --- a/2020/day-7.input +++ /dev/null @@ -1,594 +0,0 @@ -striped beige bags contain 5 dull beige bags. -dark turquoise bags contain 4 dark bronze bags, 3 posh tan bags. -mirrored turquoise bags contain 2 dim crimson bags, 4 clear crimson bags, 1 dotted blue bag. -striped gray bags contain 4 muted violet bags, 1 clear fuchsia bag, 2 dull violet bags. -bright cyan bags contain 4 dim aqua bags, 4 vibrant salmon bags. -dark aqua bags contain 4 dim brown bags. -dull magenta bags contain 5 dim plum bags, 5 dark coral bags, 3 mirrored white bags, 3 posh teal bags. -dull silver bags contain 4 dull crimson bags. -dull blue bags contain 1 shiny violet bag, 4 plaid magenta bags, 4 dull green bags. -muted white bags contain 4 dark aqua bags, 4 pale red bags, 1 striped maroon bag, 1 striped tomato bag. -shiny gray bags contain 3 dim chartreuse bags, 4 muted turquoise bags. -posh yellow bags contain 4 dim cyan bags. -wavy tan bags contain 2 plaid beige bags. -posh maroon bags contain 5 mirrored blue bags. -faded red bags contain 3 drab red bags. -striped cyan bags contain 1 bright black bag, 4 posh cyan bags, 2 striped purple bags, 1 pale fuchsia bag. -faded teal bags contain 4 vibrant gray bags, 3 dim black bags, 5 muted lime bags, 4 striped aqua bags. -striped gold bags contain 1 dotted blue bag, 5 drab bronze bags, 2 mirrored orange bags, 2 shiny violet bags. -dull cyan bags contain 5 posh teal bags, 3 pale chartreuse bags. -clear beige bags contain 3 mirrored white bags, 4 dotted orange bags, 4 muted purple bags. -posh olive bags contain 4 drab maroon bags, 2 vibrant crimson bags, 3 vibrant aqua bags, 1 dotted cyan bag. -plaid silver bags contain 2 vibrant black bags. -pale olive bags contain 2 bright turquoise bags, 5 bright teal bags. -muted plum bags contain 2 dim maroon bags, 2 pale fuchsia bags, 2 dark olive bags. -striped orange bags contain 5 pale bronze bags, 1 shiny blue bag. -dotted tan bags contain 3 dim green bags, 5 clear gray bags. -mirrored chartreuse bags contain 3 mirrored aqua bags. -dark crimson bags contain 1 dim orange bag, 4 clear lavender bags, 1 faded salmon bag, 1 muted fuchsia bag. -light violet bags contain 1 faded white bag, 2 clear purple bags. -posh bronze bags contain 5 drab coral bags. -faded olive bags contain 1 mirrored blue bag, 4 dim white bags. -drab gray bags contain 4 wavy lime bags, 2 drab chartreuse bags, 2 bright black bags, 5 clear purple bags. -plaid lavender bags contain 5 shiny aqua bags, 1 mirrored gold bag. -faded green bags contain 5 pale lavender bags, 2 pale red bags. -dark orange bags contain 5 dull plum bags. -clear violet bags contain 1 dull lime bag, 5 dim brown bags, 5 mirrored bronze bags, 3 dotted turquoise bags. -mirrored aqua bags contain 3 dull beige bags, 2 dotted lavender bags. -clear bronze bags contain 3 mirrored magenta bags, 4 dark tomato bags. -pale gray bags contain 5 mirrored orange bags, 3 dotted bronze bags, 3 dark tomato bags. -light yellow bags contain 3 drab silver bags, 3 dull olive bags, 5 light violet bags. -bright aqua bags contain 2 muted silver bags, 1 striped turquoise bag. -vibrant black bags contain 2 clear cyan bags, 2 striped turquoise bags. -light black bags contain 1 shiny gray bag, 3 drab gray bags. -dotted plum bags contain 3 wavy teal bags, 4 bright violet bags, 2 vibrant purple bags. -dark tomato bags contain 3 dotted indigo bags, 2 plaid teal bags, 4 pale lavender bags. -pale violet bags contain 5 vibrant plum bags, 3 striped teal bags, 2 muted magenta bags, 3 dark brown bags. -dark green bags contain 5 shiny green bags, 4 bright black bags, 3 dull beige bags. -striped crimson bags contain 4 dark gray bags. -bright gray bags contain 5 muted indigo bags, 5 dark lime bags, 3 bright plum bags. -dull gray bags contain 3 vibrant fuchsia bags. -drab black bags contain 4 bright turquoise bags, 4 striped chartreuse bags, 4 faded white bags, 4 plaid silver bags. -pale purple bags contain 1 vibrant aqua bag, 2 dotted beige bags, 1 light tomato bag. -dotted indigo bags contain 5 dotted lavender bags, 5 shiny gold bags, 1 vibrant tomato bag, 1 striped purple bag. -clear brown bags contain 3 light olive bags, 1 shiny beige bag. -faded salmon bags contain no other bags. -posh salmon bags contain 3 wavy salmon bags, 2 striped blue bags. -shiny cyan bags contain 5 dull salmon bags, 5 clear chartreuse bags. -drab white bags contain 3 vibrant fuchsia bags, 2 faded black bags, 3 plaid teal bags. -faded plum bags contain 4 muted teal bags, 4 light gray bags, 4 drab magenta bags, 2 plaid aqua bags. -dim gold bags contain 3 muted bronze bags. -wavy cyan bags contain 3 vibrant lavender bags. -pale tan bags contain 4 pale aqua bags, 1 striped black bag, 3 posh tan bags. -shiny plum bags contain 1 dim cyan bag, 3 dim aqua bags, 4 bright crimson bags, 5 mirrored white bags. -faded turquoise bags contain 4 faded lavender bags, 5 posh silver bags. -shiny teal bags contain 3 dull salmon bags, 4 drab beige bags, 4 wavy lime bags, 5 pale white bags. -clear white bags contain 1 dotted tomato bag. -plaid black bags contain 4 bright plum bags, 4 shiny tomato bags, 2 plaid green bags, 3 faded blue bags. -vibrant gold bags contain 3 mirrored white bags, 5 striped turquoise bags. -plaid tan bags contain 3 mirrored brown bags, 1 posh maroon bag, 1 mirrored red bag. -light gold bags contain 1 plaid aqua bag, 2 drab crimson bags, 4 posh bronze bags, 3 shiny bronze bags. -dotted lime bags contain 2 pale green bags, 2 shiny bronze bags, 1 vibrant salmon bag. -plaid orange bags contain 2 dark tan bags, 3 plaid teal bags, 4 faded black bags, 2 wavy tomato bags. -bright magenta bags contain 2 vibrant red bags, 1 muted teal bag, 5 mirrored crimson bags. -striped white bags contain 1 dotted white bag, 3 vibrant tomato bags. -muted lavender bags contain 4 faded gold bags, 3 pale red bags. -dotted red bags contain 1 clear magenta bag, 4 posh tan bags. -shiny yellow bags contain 2 dark brown bags. -muted turquoise bags contain 2 posh fuchsia bags, 5 dark tan bags, 2 wavy blue bags. -mirrored teal bags contain 1 posh cyan bag, 2 dull orange bags, 5 bright indigo bags. -dark yellow bags contain 5 bright indigo bags. -mirrored violet bags contain 4 light maroon bags, 2 shiny plum bags, 2 dark coral bags. -dim coral bags contain 5 shiny red bags, 1 dim plum bag. -pale plum bags contain 5 dull gold bags, 1 muted teal bag, 2 faded cyan bags. -vibrant violet bags contain 5 wavy bronze bags, 4 wavy orange bags. -light gray bags contain 2 bright teal bags, 4 dotted olive bags, 2 striped magenta bags. -drab silver bags contain 2 vibrant beige bags, 3 striped gold bags. -mirrored coral bags contain 5 muted magenta bags, 4 vibrant green bags. -muted tan bags contain 1 vibrant bronze bag. -clear turquoise bags contain 5 mirrored lime bags. -faded orange bags contain 1 muted silver bag, 1 light fuchsia bag. -dotted bronze bags contain 1 faded salmon bag, 1 dim tomato bag, 2 dull beige bags, 4 vibrant tomato bags. -mirrored silver bags contain 5 clear fuchsia bags. -bright black bags contain no other bags. -vibrant teal bags contain 5 dim coral bags. -wavy chartreuse bags contain 1 dim tomato bag, 1 drab orange bag, 3 mirrored gold bags. -wavy green bags contain 5 dark cyan bags, 4 wavy lime bags. -wavy tomato bags contain 3 vibrant black bags, 4 faded gold bags, 1 striped turquoise bag, 5 plaid teal bags. -clear gray bags contain 2 clear lime bags. -dull teal bags contain 3 drab orange bags, 2 light fuchsia bags, 3 drab tomato bags. -faded chartreuse bags contain 1 posh fuchsia bag, 3 dark coral bags, 4 drab crimson bags. -striped silver bags contain 4 dim chartreuse bags. -shiny blue bags contain 2 dull salmon bags. -muted purple bags contain 2 clear lime bags, 2 light blue bags, 3 dim lime bags. -clear magenta bags contain 5 light blue bags, 3 wavy salmon bags, 1 muted green bag, 5 dark tan bags. -dotted blue bags contain 1 striped turquoise bag, 2 pale indigo bags, 3 posh salmon bags. -bright green bags contain 5 light lavender bags, 1 dull beige bag, 3 plaid gold bags. -posh silver bags contain 4 plaid fuchsia bags. -posh gold bags contain 5 dim magenta bags, 4 posh fuchsia bags, 5 muted silver bags. -wavy crimson bags contain 4 plaid orange bags. -dark magenta bags contain 4 pale salmon bags, 1 dotted aqua bag, 4 drab magenta bags, 1 pale olive bag. -dim red bags contain 3 bright crimson bags, 2 mirrored lime bags. -dull white bags contain 5 pale cyan bags, 1 dark orange bag, 4 mirrored plum bags. -plaid lime bags contain 3 vibrant magenta bags, 5 wavy cyan bags. -dim brown bags contain no other bags. -pale black bags contain 3 mirrored gold bags, 3 clear gold bags, 2 dark chartreuse bags. -clear teal bags contain 1 mirrored blue bag, 5 muted teal bags, 4 dotted magenta bags, 3 bright crimson bags. -muted aqua bags contain 3 dotted aqua bags, 2 dull aqua bags, 1 muted lavender bag, 2 muted green bags. -plaid crimson bags contain 1 mirrored indigo bag. -bright coral bags contain 3 mirrored gold bags, 2 wavy salmon bags, 5 pale crimson bags, 2 dark brown bags. -dotted fuchsia bags contain 4 vibrant coral bags, 3 mirrored teal bags, 2 pale lavender bags. -dark lavender bags contain 3 dotted red bags. -clear fuchsia bags contain 3 dotted blue bags, 2 posh brown bags. -vibrant turquoise bags contain 4 clear blue bags, 2 mirrored gray bags. -posh tomato bags contain 2 muted bronze bags, 1 dark magenta bag. -bright plum bags contain 4 posh tan bags, 5 faded salmon bags. -dim beige bags contain 4 plaid teal bags, 2 drab bronze bags. -light coral bags contain 2 dotted bronze bags, 4 shiny gold bags, 2 bright plum bags, 1 dim tan bag. -striped violet bags contain 5 vibrant maroon bags, 3 posh cyan bags, 2 faded salmon bags. -pale maroon bags contain 4 pale aqua bags, 5 shiny silver bags. -plaid green bags contain 2 light tomato bags. -vibrant lavender bags contain 1 dim lime bag. -posh teal bags contain 5 vibrant lavender bags. -dull crimson bags contain 1 dark brown bag. -muted bronze bags contain 4 vibrant cyan bags, 1 posh chartreuse bag, 1 dotted bronze bag. -posh red bags contain 4 muted tomato bags, 1 vibrant tomato bag, 4 dark brown bags. -striped lime bags contain 2 dull plum bags, 5 drab yellow bags, 2 pale silver bags. -dull black bags contain 1 dim gray bag, 2 drab aqua bags, 3 faded blue bags, 2 mirrored indigo bags. -vibrant red bags contain 3 faded black bags, 4 wavy red bags, 5 wavy salmon bags. -drab olive bags contain 3 dull magenta bags, 1 vibrant aqua bag, 2 dim maroon bags. -muted yellow bags contain 5 wavy lime bags, 2 vibrant brown bags, 2 shiny cyan bags. -dim lavender bags contain 1 wavy salmon bag. -posh tan bags contain 4 mirrored lime bags, 5 faded gold bags. -vibrant magenta bags contain 4 plaid teal bags, 3 wavy plum bags, 1 pale cyan bag, 2 mirrored bronze bags. -dim yellow bags contain 3 vibrant black bags, 1 dim maroon bag. -drab orange bags contain 2 plaid green bags, 5 clear purple bags, 5 bright beige bags, 5 dull violet bags. -plaid magenta bags contain 4 pale tan bags, 4 vibrant lavender bags, 1 drab coral bag, 5 dark lime bags. -dark gold bags contain 1 posh tomato bag, 3 muted teal bags. -faded black bags contain 2 bright turquoise bags, 1 striped blue bag, 1 striped purple bag. -striped black bags contain 1 shiny silver bag. -dull purple bags contain 2 faded lavender bags, 4 mirrored tomato bags. -dull lime bags contain 5 wavy olive bags. -dotted black bags contain 5 dotted olive bags. -light maroon bags contain 1 shiny orange bag, 1 bright black bag, 1 pale tan bag. -muted silver bags contain 4 dotted purple bags, 3 faded salmon bags, 1 drab magenta bag, 4 bright green bags. -muted maroon bags contain 5 dim lime bags, 1 wavy plum bag, 1 striped lavender bag, 1 dotted white bag. -shiny coral bags contain 1 dim yellow bag, 1 muted crimson bag, 4 dim olive bags. -shiny beige bags contain 5 shiny orange bags, 5 plaid teal bags. -striped brown bags contain 5 bright white bags, 1 faded gold bag, 4 dim teal bags. -drab salmon bags contain 5 faded tomato bags, 4 muted crimson bags. -shiny magenta bags contain 4 wavy green bags, 2 dark white bags, 5 clear olive bags. -light blue bags contain 3 drab brown bags, 5 dim magenta bags, 3 light fuchsia bags, 1 dotted lavender bag. -dim crimson bags contain 3 striped chartreuse bags. -dotted orange bags contain 4 bright olive bags. -dotted beige bags contain 5 vibrant chartreuse bags, 2 faded purple bags, 3 pale beige bags. -bright tomato bags contain 2 muted gray bags, 5 pale lavender bags, 2 light cyan bags, 4 dotted gold bags. -dim green bags contain 3 wavy lime bags. -dotted white bags contain 2 dim gray bags, 1 faded white bag, 4 faded plum bags. -striped red bags contain 2 dark gold bags. -dotted salmon bags contain 1 bright bronze bag, 1 wavy bronze bag. -muted gold bags contain 4 mirrored teal bags. -light chartreuse bags contain 4 posh tomato bags. -dark lime bags contain 3 striped teal bags, 5 dotted purple bags, 1 striped turquoise bag. -pale lavender bags contain 4 striped maroon bags, 5 dim red bags, 5 dim lime bags. -striped bronze bags contain 5 vibrant fuchsia bags, 2 dull orange bags, 1 wavy purple bag. -drab fuchsia bags contain 2 dotted lavender bags, 1 clear purple bag, 3 dark purple bags. -mirrored gold bags contain 4 dark tomato bags, 5 pale tan bags, 2 bright indigo bags, 5 wavy teal bags. -posh gray bags contain 2 drab magenta bags, 3 dark tan bags. -posh cyan bags contain 2 pale olive bags, 5 dull coral bags. -pale beige bags contain 5 striped cyan bags, 5 shiny violet bags. -faded maroon bags contain 1 striped turquoise bag, 4 dim brown bags, 5 plaid gold bags, 1 vibrant lavender bag. -mirrored purple bags contain 1 striped yellow bag, 4 dotted chartreuse bags, 5 muted crimson bags, 5 dull crimson bags. -faded coral bags contain 1 plaid aqua bag, 5 muted coral bags. -dull indigo bags contain 4 dull silver bags. -faded purple bags contain 1 muted turquoise bag, 3 pale red bags, 2 pale lavender bags, 1 shiny bronze bag. -shiny crimson bags contain 3 mirrored blue bags, 2 striped turquoise bags, 5 striped teal bags, 4 dim lime bags. -light turquoise bags contain 2 dark gray bags, 5 mirrored white bags. -posh fuchsia bags contain 2 plaid gold bags. -bright purple bags contain 1 dark lime bag, 4 vibrant bronze bags, 5 clear gold bags, 2 dull brown bags. -drab red bags contain 5 striped blue bags. -mirrored lavender bags contain 2 pale indigo bags, 3 striped maroon bags, 1 plaid gold bag. -muted tomato bags contain 3 striped cyan bags, 4 dotted indigo bags. -light orange bags contain 4 light maroon bags, 4 striped black bags, 1 vibrant white bag. -shiny lime bags contain 2 bright chartreuse bags, 4 dull salmon bags, 2 clear olive bags, 1 mirrored white bag. -dim plum bags contain 4 drab magenta bags, 4 dim red bags. -dark purple bags contain 2 dotted crimson bags, 2 dotted orange bags, 3 striped maroon bags. -drab aqua bags contain 3 striped black bags, 1 dim red bag. -wavy red bags contain 4 vibrant purple bags, 3 plaid teal bags, 5 drab aqua bags. -wavy turquoise bags contain 4 clear maroon bags, 2 faded silver bags, 4 dotted teal bags. -muted cyan bags contain 5 wavy yellow bags. -drab cyan bags contain 3 faded green bags, 5 dull orange bags, 3 pale tan bags, 3 mirrored brown bags. -wavy violet bags contain 3 light lavender bags. -light red bags contain 2 wavy blue bags. -drab beige bags contain 3 mirrored indigo bags, 2 mirrored blue bags. -pale tomato bags contain 2 wavy green bags, 3 clear orange bags, 3 dull blue bags, 1 light lime bag. -posh lime bags contain 4 dull lime bags. -wavy olive bags contain 3 shiny maroon bags, 3 dark turquoise bags, 2 dull red bags. -dull chartreuse bags contain 4 muted coral bags. -muted black bags contain 3 mirrored blue bags, 1 faded white bag, 1 dull beige bag. -dark indigo bags contain 1 muted silver bag, 3 dim plum bags. -mirrored cyan bags contain 3 vibrant silver bags, 1 posh teal bag. -plaid olive bags contain 2 muted teal bags, 5 clear cyan bags, 5 drab magenta bags. -vibrant white bags contain 2 dark gray bags, 1 dim gray bag, 4 striped magenta bags. -wavy bronze bags contain 1 plaid aqua bag, 1 light tomato bag, 2 mirrored tomato bags, 4 pale olive bags. -plaid chartreuse bags contain 4 wavy coral bags, 3 dotted beige bags, 2 bright maroon bags, 1 pale lime bag. -dark tan bags contain 1 drab brown bag, 5 dull orange bags. -shiny olive bags contain 5 posh black bags, 4 faded plum bags. -pale lime bags contain 1 dull black bag. -muted crimson bags contain 3 dim cyan bags, 1 vibrant olive bag, 1 striped purple bag, 5 faded gold bags. -dark salmon bags contain 5 muted turquoise bags. -dark silver bags contain 5 mirrored salmon bags, 4 dim lavender bags, 2 shiny crimson bags, 2 bright gray bags. -clear cyan bags contain 3 muted crimson bags. -muted orange bags contain 1 faded maroon bag, 1 posh gold bag, 1 bright turquoise bag, 4 clear cyan bags. -dark fuchsia bags contain 3 bright turquoise bags. -mirrored bronze bags contain 1 vibrant tomato bag, 2 drab brown bags, 1 faded purple bag. -dim orange bags contain 4 vibrant brown bags, 1 dotted lavender bag. -shiny turquoise bags contain 5 dim violet bags, 5 dim teal bags, 3 faded tomato bags. -light tan bags contain 1 bright beige bag, 2 mirrored indigo bags. -dull olive bags contain 2 pale coral bags. -faded cyan bags contain 2 dotted chartreuse bags, 2 pale salmon bags, 3 dull lavender bags, 3 dotted maroon bags. -shiny green bags contain 4 mirrored white bags. -drab violet bags contain 4 vibrant coral bags, 4 dim olive bags, 5 plaid brown bags, 2 bright tan bags. -posh violet bags contain 1 shiny crimson bag, 1 faded indigo bag. -shiny tomato bags contain 2 dim cyan bags. -wavy indigo bags contain 4 mirrored violet bags, 5 faded maroon bags, 3 drab gray bags, 1 plaid orange bag. -posh brown bags contain 4 mirrored coral bags, 5 drab cyan bags, 5 striped cyan bags, 1 muted lavender bag. -dull tomato bags contain 2 drab aqua bags, 4 muted orange bags, 4 faded gold bags. -dim silver bags contain 4 posh gray bags. -plaid indigo bags contain 2 dim indigo bags. -dull coral bags contain 2 shiny plum bags. -mirrored plum bags contain 4 vibrant green bags, 5 striped fuchsia bags. -light bronze bags contain 5 vibrant purple bags. -mirrored white bags contain 3 bright teal bags. -vibrant indigo bags contain 4 vibrant lime bags. -vibrant crimson bags contain 3 dim lavender bags, 1 plaid teal bag. -vibrant salmon bags contain 2 dull green bags, 2 dark coral bags, 1 pale fuchsia bag, 3 pale aqua bags. -mirrored fuchsia bags contain 1 plaid maroon bag, 1 dark aqua bag, 4 wavy violet bags, 4 posh tomato bags. -bright crimson bags contain 3 light lavender bags, 1 striped purple bag. -shiny purple bags contain 4 light aqua bags, 4 faded black bags, 1 dull green bag, 3 dotted gold bags. -dim tomato bags contain 2 striped purple bags, 4 light lavender bags, 1 mirrored lime bag. -dull bronze bags contain 1 mirrored tomato bag, 5 faded white bags, 1 wavy teal bag. -vibrant chartreuse bags contain 5 pale indigo bags, 5 mirrored violet bags. -vibrant aqua bags contain 3 muted gray bags, 5 clear cyan bags, 4 striped black bags. -clear crimson bags contain 4 pale coral bags, 3 clear tomato bags, 3 wavy blue bags. -drab blue bags contain 3 dark magenta bags, 4 muted orange bags, 4 wavy lime bags. -bright red bags contain 1 dull green bag, 1 muted tomato bag. -bright white bags contain 3 dark black bags, 4 dotted magenta bags, 1 dull orange bag, 4 dotted purple bags. -dotted brown bags contain 3 clear lime bags, 3 drab gray bags, 4 faded black bags, 1 striped brown bag. -vibrant cyan bags contain 3 drab aqua bags. -mirrored crimson bags contain 5 vibrant aqua bags, 4 dim brown bags, 1 dark indigo bag. -drab bronze bags contain 1 striped black bag, 3 dark bronze bags, 4 wavy yellow bags. -vibrant tomato bags contain 3 vibrant olive bags, 1 plaid gold bag, 1 dim tomato bag. -bright silver bags contain 2 dark chartreuse bags, 5 light beige bags, 5 dim tomato bags, 1 drab chartreuse bag. -dull violet bags contain 5 plaid bronze bags, 5 muted black bags, 2 light fuchsia bags. -dull beige bags contain no other bags. -mirrored green bags contain 5 muted teal bags, 1 dim aqua bag, 2 clear lime bags, 3 dim tomato bags. -wavy plum bags contain 3 clear olive bags. -dull brown bags contain 1 vibrant plum bag, 4 plaid maroon bags. -pale fuchsia bags contain 4 dotted lavender bags, 5 shiny beige bags. -dim lime bags contain no other bags. -light lavender bags contain 3 mirrored lime bags, 5 muted olive bags, 3 dim brown bags, 2 faded salmon bags. -posh indigo bags contain 1 dotted blue bag, 5 striped plum bags. -dull turquoise bags contain 4 plaid teal bags, 2 muted silver bags. -posh purple bags contain 1 pale green bag, 2 wavy olive bags. -light teal bags contain 1 bright brown bag, 3 mirrored crimson bags, 4 posh aqua bags. -vibrant beige bags contain 3 faded gold bags, 4 clear olive bags. -wavy fuchsia bags contain 5 mirrored teal bags, 4 dotted magenta bags, 5 drab orange bags. -posh magenta bags contain 1 dotted lavender bag, 2 dull magenta bags, 5 clear plum bags, 3 dim chartreuse bags. -pale salmon bags contain 3 faded salmon bags, 2 drab magenta bags, 3 dark brown bags, 4 dull beige bags. -wavy silver bags contain 2 pale teal bags. -shiny salmon bags contain 2 clear red bags, 2 mirrored yellow bags, 2 wavy indigo bags, 3 vibrant lavender bags. -faded violet bags contain 1 wavy yellow bag. -bright lime bags contain 1 mirrored bronze bag. -dark plum bags contain 5 light blue bags, 3 dim gray bags. -dark gray bags contain 2 drab magenta bags. -vibrant blue bags contain 3 dark lime bags, 2 posh gold bags. -dotted tomato bags contain 2 dotted bronze bags. -plaid purple bags contain 4 wavy beige bags, 5 muted lavender bags, 5 pale red bags. -striped maroon bags contain 4 shiny maroon bags, 5 dull crimson bags. -wavy brown bags contain 1 wavy gray bag. -bright brown bags contain 4 muted gray bags, 2 dark magenta bags, 4 muted lavender bags, 4 pale tan bags. -wavy gray bags contain 5 bright teal bags, 3 clear purple bags, 5 vibrant lime bags, 1 bright plum bag. -pale white bags contain 2 dark magenta bags. -dim blue bags contain 4 dark white bags. -muted beige bags contain 5 pale magenta bags, 1 dark olive bag. -plaid coral bags contain 2 mirrored salmon bags, 2 vibrant gold bags, 3 drab bronze bags, 3 faded gold bags. -drab teal bags contain 1 dotted blue bag, 1 faded chartreuse bag. -wavy gold bags contain 2 faded turquoise bags, 1 faded coral bag, 3 striped purple bags, 5 wavy white bags. -vibrant lime bags contain 1 striped plum bag, 5 mirrored indigo bags, 2 pale coral bags. -clear plum bags contain 2 vibrant tomato bags, 5 light lavender bags. -dim fuchsia bags contain 1 vibrant maroon bag, 1 shiny white bag, 5 dark orange bags, 1 light coral bag. -plaid beige bags contain 4 mirrored fuchsia bags, 4 faded green bags. -light olive bags contain 3 dim indigo bags. -dark beige bags contain 5 dull silver bags, 2 pale indigo bags. -bright olive bags contain 3 dotted gold bags, 4 faded gold bags, 2 drab crimson bags. -plaid plum bags contain 4 vibrant orange bags. -muted coral bags contain 2 vibrant maroon bags. -wavy orange bags contain 2 drab crimson bags, 3 dull cyan bags, 1 mirrored coral bag. -bright tan bags contain 5 muted violet bags, 1 pale tan bag, 3 light maroon bags. -plaid blue bags contain 4 muted lavender bags, 1 striped black bag, 5 pale indigo bags. -wavy beige bags contain 4 pale maroon bags. -pale green bags contain 2 shiny silver bags. -plaid tomato bags contain 2 dull plum bags, 1 dotted gold bag, 3 shiny red bags. -dotted crimson bags contain 3 muted silver bags. -faded indigo bags contain 1 vibrant black bag, 2 posh bronze bags. -drab brown bags contain 3 mirrored lime bags, 5 faded maroon bags, 4 vibrant lavender bags, 1 vibrant tomato bag. -dotted chartreuse bags contain 3 dull crimson bags, 2 dotted bronze bags. -dull green bags contain 3 wavy violet bags. -mirrored gray bags contain 1 dim fuchsia bag, 1 dull green bag, 3 posh crimson bags, 4 vibrant purple bags. -shiny lavender bags contain 4 shiny blue bags, 2 dim beige bags. -faded blue bags contain 2 dim lime bags, 3 muted teal bags. -mirrored indigo bags contain 2 mirrored white bags, 3 faded blue bags, 4 dotted purple bags, 4 dim magenta bags. -wavy white bags contain 4 faded olive bags. -dull aqua bags contain 4 pale red bags, 5 dim gray bags, 2 shiny maroon bags, 5 light blue bags. -dark red bags contain 3 muted brown bags. -mirrored magenta bags contain 4 dim tomato bags, 5 dim maroon bags, 3 mirrored fuchsia bags. -dark white bags contain 3 striped cyan bags, 1 clear teal bag, 3 dim maroon bags, 2 dull aqua bags. -dotted magenta bags contain 3 shiny silver bags. -bright maroon bags contain 5 vibrant purple bags, 2 drab purple bags, 2 light cyan bags, 1 dull black bag. -plaid teal bags contain 1 bright black bag, 5 mirrored white bags. -drab yellow bags contain 4 clear purple bags, 1 vibrant olive bag. -mirrored orange bags contain 1 striped cyan bag, 2 vibrant cyan bags, 1 dark white bag. -bright orange bags contain 5 shiny gold bags, 3 dull turquoise bags. -faded bronze bags contain 1 posh turquoise bag, 3 muted beige bags. -wavy teal bags contain 5 mirrored indigo bags. -striped aqua bags contain 4 mirrored crimson bags, 2 mirrored salmon bags, 4 light violet bags, 5 dotted magenta bags. -bright chartreuse bags contain 4 wavy green bags, 5 drab gray bags. -light cyan bags contain 3 dim brown bags. -plaid violet bags contain 1 dotted red bag, 4 bright lavender bags. -clear salmon bags contain 4 drab bronze bags. -light magenta bags contain 2 dark turquoise bags, 2 drab chartreuse bags, 5 dim chartreuse bags, 3 pale salmon bags. -wavy lime bags contain 1 dark turquoise bag, 3 striped turquoise bags, 1 pale chartreuse bag. -dotted gray bags contain 2 wavy tomato bags, 2 shiny tomato bags, 2 dark coral bags. -wavy lavender bags contain 3 dull blue bags, 1 faded fuchsia bag. -clear black bags contain 3 dim plum bags, 1 striped silver bag. -bright yellow bags contain 4 striped violet bags. -posh blue bags contain 5 plaid turquoise bags. -dotted green bags contain 3 vibrant silver bags. -plaid white bags contain 4 dim coral bags, 4 faded aqua bags, 2 mirrored teal bags. -striped fuchsia bags contain 5 dull blue bags, 1 clear olive bag. -dark bronze bags contain 1 dotted bronze bag. -vibrant silver bags contain 2 light maroon bags, 5 dotted purple bags. -dark cyan bags contain 5 pale fuchsia bags, 5 faded black bags, 4 dark magenta bags. -pale teal bags contain 2 vibrant lime bags, 1 dim orange bag, 3 muted aqua bags. -drab coral bags contain 5 shiny silver bags. -light aqua bags contain 4 plaid aqua bags, 4 light fuchsia bags, 4 plaid bronze bags, 4 mirrored bronze bags. -pale cyan bags contain 5 drab maroon bags, 1 shiny crimson bag. -muted chartreuse bags contain 2 pale lime bags. -pale aqua bags contain 4 striped purple bags. -clear lime bags contain 1 wavy salmon bag, 3 dim cyan bags, 4 muted crimson bags. -dim magenta bags contain 2 faded salmon bags, 1 posh fuchsia bag, 1 muted teal bag. -drab gold bags contain 3 faded magenta bags, 4 pale cyan bags. -muted fuchsia bags contain 2 pale aqua bags, 3 dotted aqua bags, 4 light fuchsia bags, 1 posh fuchsia bag. -pale orange bags contain 1 faded blue bag. -dim white bags contain 5 shiny silver bags, 1 shiny tomato bag, 5 faded gold bags, 2 dull crimson bags. -shiny violet bags contain 4 pale tan bags, 5 muted olive bags, 3 dull turquoise bags, 2 bright aqua bags. -plaid aqua bags contain 5 vibrant crimson bags, 5 muted purple bags, 5 dim maroon bags. -mirrored yellow bags contain 2 faded silver bags. -mirrored maroon bags contain 1 posh indigo bag. -clear maroon bags contain 2 dim aqua bags, 5 striped blue bags, 3 dark bronze bags, 3 dull turquoise bags. -dim black bags contain 5 striped purple bags, 1 mirrored aqua bag. -posh turquoise bags contain 4 light fuchsia bags, 3 wavy plum bags, 5 dark lavender bags. -bright blue bags contain 3 faded chartreuse bags, 5 shiny tomato bags. -dark violet bags contain 4 clear turquoise bags, 2 vibrant fuchsia bags, 4 bright red bags. -striped green bags contain 5 wavy silver bags, 1 posh lavender bag, 5 dark gold bags, 3 dark tan bags. -posh crimson bags contain 4 dotted gray bags, 1 shiny crimson bag. -dotted maroon bags contain 5 muted orange bags. -bright beige bags contain 4 faded salmon bags, 5 clear chartreuse bags, 1 drab maroon bag, 3 pale red bags. -drab chartreuse bags contain 2 pale maroon bags. -drab crimson bags contain 2 striped teal bags, 1 light lavender bag, 4 bright crimson bags. -pale gold bags contain 1 faded blue bag, 2 mirrored bronze bags, 1 muted aqua bag, 5 striped magenta bags. -pale yellow bags contain 5 light indigo bags, 3 posh purple bags. -dotted violet bags contain 2 muted black bags, 1 pale magenta bag, 2 clear green bags, 5 vibrant chartreuse bags. -dim olive bags contain 1 plaid teal bag, 5 mirrored lime bags, 5 mirrored beige bags, 2 light aqua bags. -striped teal bags contain 5 dark brown bags, 4 plaid gold bags, 2 striped turquoise bags, 2 mirrored lime bags. -light salmon bags contain 3 vibrant silver bags, 3 faded green bags, 4 dull cyan bags, 3 light aqua bags. -dim indigo bags contain 2 dull red bags, 1 shiny tomato bag, 5 posh tan bags, 5 bright lime bags. -dark chartreuse bags contain 5 shiny red bags. -light lime bags contain 3 bright olive bags, 4 pale chartreuse bags, 1 wavy tomato bag. -posh aqua bags contain 2 dim fuchsia bags, 2 dotted blue bags. -light silver bags contain 4 striped cyan bags. -mirrored brown bags contain 2 dotted lavender bags. -muted blue bags contain 3 drab fuchsia bags. -vibrant olive bags contain no other bags. -clear orange bags contain 5 mirrored aqua bags. -clear purple bags contain 3 muted silver bags. -dim turquoise bags contain 2 muted turquoise bags. -muted olive bags contain 5 faded salmon bags, 5 dim lime bags. -faded lime bags contain 2 muted red bags, 2 dim crimson bags. -light fuchsia bags contain no other bags. -drab lavender bags contain 4 pale lime bags. -posh coral bags contain 1 striped violet bag, 1 dull cyan bag. -striped turquoise bags contain 3 vibrant olive bags, 2 dotted purple bags, 5 bright crimson bags. -vibrant bronze bags contain 4 striped magenta bags, 3 dull beige bags, 3 shiny tomato bags, 3 clear cyan bags. -faded beige bags contain 4 shiny orange bags, 5 vibrant beige bags. -plaid red bags contain 5 mirrored crimson bags, 1 dull crimson bag, 5 striped aqua bags, 4 posh tan bags. -muted teal bags contain 5 shiny maroon bags, 4 dim brown bags, 3 faded gold bags. -vibrant green bags contain 5 faded maroon bags. -posh lavender bags contain 2 light lime bags, 1 pale lavender bag, 1 vibrant orange bag. -pale crimson bags contain 2 vibrant tan bags, 3 bright beige bags. -wavy black bags contain 3 wavy fuchsia bags, 5 striped blue bags, 2 mirrored brown bags, 2 bright teal bags. -mirrored beige bags contain 2 clear plum bags, 2 faded orange bags. -striped tan bags contain 5 wavy crimson bags, 1 posh maroon bag, 4 striped coral bags, 3 pale lavender bags. -dim maroon bags contain 5 vibrant black bags. -plaid gold bags contain 2 mirrored lime bags, 5 bright black bags, 2 light fuchsia bags, 1 dull beige bag. -shiny orange bags contain 2 vibrant olive bags, 2 shiny green bags, 3 striped blue bags. -striped magenta bags contain 5 bright orange bags, 1 dotted purple bag, 3 muted fuchsia bags, 1 dim tan bag. -light white bags contain 4 light tomato bags, 3 faded tomato bags, 5 posh silver bags, 4 clear beige bags. -posh green bags contain 4 plaid fuchsia bags. -striped chartreuse bags contain 3 vibrant silver bags, 3 striped olive bags, 5 dark aqua bags, 4 muted tomato bags. -posh black bags contain 1 striped chartreuse bag. -muted red bags contain 3 dim red bags. -faded tomato bags contain 4 plaid silver bags. -dotted lavender bags contain 1 dim tomato bag, 3 dim brown bags, 4 posh tan bags. -dim violet bags contain 3 muted black bags, 3 muted teal bags. -bright turquoise bags contain 2 dim tomato bags, 1 dim cyan bag, 4 dotted bronze bags. -faded white bags contain 1 posh gold bag, 5 vibrant tomato bags, 5 wavy yellow bags. -dark coral bags contain 3 shiny green bags. -posh chartreuse bags contain 5 shiny maroon bags, 4 muted teal bags. -drab purple bags contain 1 mirrored teal bag, 3 clear silver bags. -faded silver bags contain 1 clear plum bag, 4 drab chartreuse bags, 1 pale olive bag, 1 mirrored white bag. -pale silver bags contain 5 light crimson bags. -pale red bags contain 5 bright aqua bags, 2 muted gray bags, 4 shiny orange bags. -plaid fuchsia bags contain 3 shiny beige bags, 3 dull aqua bags. -faded yellow bags contain 4 plaid fuchsia bags, 3 vibrant purple bags, 3 dim lime bags. -shiny black bags contain 1 dark turquoise bag, 3 muted red bags, 1 faded yellow bag, 3 bright beige bags. -clear indigo bags contain 1 bright bronze bag, 4 drab gold bags. -dim tan bags contain 1 dim cyan bag, 1 clear chartreuse bag, 5 vibrant olive bags. -vibrant orange bags contain 2 muted orange bags, 5 vibrant aqua bags, 4 shiny beige bags, 2 dim maroon bags. -shiny bronze bags contain 4 muted fuchsia bags, 1 posh gold bag, 3 faded salmon bags. -striped indigo bags contain 3 dark tan bags, 2 faded gold bags, 5 drab black bags. -vibrant purple bags contain 4 pale salmon bags, 1 mirrored bronze bag, 4 vibrant tomato bags, 2 dark bronze bags. -clear silver bags contain 3 dull orange bags. -clear tan bags contain 3 vibrant cyan bags, 5 pale cyan bags, 3 mirrored silver bags. -muted indigo bags contain 1 pale salmon bag, 4 bright aqua bags. -striped yellow bags contain 5 posh fuchsia bags, 3 dotted lavender bags, 5 shiny green bags. -dotted coral bags contain 2 faded plum bags, 5 vibrant tan bags, 3 mirrored lavender bags, 3 vibrant yellow bags. -striped coral bags contain 1 bright indigo bag, 5 pale chartreuse bags, 1 faded salmon bag. -dark olive bags contain 5 bright crimson bags. -clear aqua bags contain 4 light gold bags, 3 dull turquoise bags. -muted brown bags contain 1 dark magenta bag, 1 dotted plum bag, 4 plaid gray bags, 3 clear teal bags. -vibrant yellow bags contain 4 muted crimson bags, 2 drab white bags, 4 mirrored purple bags, 1 drab yellow bag. -wavy purple bags contain 3 shiny orange bags, 2 pale beige bags, 5 clear beige bags, 3 dotted purple bags. -shiny silver bags contain no other bags. -clear chartreuse bags contain 5 dim lime bags, 4 faded maroon bags. -wavy magenta bags contain 2 light lavender bags, 1 dark turquoise bag. -light brown bags contain 4 dotted gray bags, 2 drab bronze bags, 3 dark yellow bags. -faded lavender bags contain 2 wavy salmon bags, 4 bright olive bags. -shiny tan bags contain 3 dark turquoise bags, 4 posh gold bags, 4 shiny red bags. -dotted aqua bags contain 3 faded blue bags, 5 dark bronze bags. -light purple bags contain 5 dark gray bags, 1 faded yellow bag. -faded brown bags contain 4 muted violet bags, 3 muted tomato bags, 3 drab lime bags, 1 vibrant cyan bag. -wavy yellow bags contain 3 faded gold bags, 2 shiny maroon bags. -posh beige bags contain 5 faded magenta bags, 5 muted aqua bags, 5 wavy red bags. -faded magenta bags contain 2 muted lavender bags, 2 pale red bags, 1 vibrant plum bag, 4 vibrant tan bags. -vibrant gray bags contain 4 clear plum bags, 1 vibrant olive bag. -dull lavender bags contain 1 pale lime bag, 2 bright gray bags, 2 clear blue bags, 3 vibrant silver bags. -mirrored tomato bags contain 1 clear chartreuse bag, 2 pale red bags, 4 dim plum bags, 4 pale chartreuse bags. -dull tan bags contain 3 vibrant cyan bags, 3 shiny orange bags, 4 clear brown bags. -dull fuchsia bags contain 5 light aqua bags, 2 clear purple bags, 2 shiny white bags, 2 dark lime bags. -striped plum bags contain 3 drab aqua bags, 2 bright green bags, 2 plaid olive bags. -dotted teal bags contain 5 drab purple bags, 2 vibrant brown bags. -vibrant tan bags contain 1 faded gray bag, 4 faded purple bags, 2 mirrored green bags, 1 drab chartreuse bag. -muted magenta bags contain 5 pale maroon bags, 1 dim brown bag. -muted lime bags contain 5 dark blue bags, 1 dim olive bag, 2 wavy gray bags. -drab tomato bags contain 3 plaid maroon bags. -dull red bags contain 5 light coral bags, 5 dotted purple bags, 5 muted plum bags. -striped tomato bags contain 3 faded black bags, 2 striped cyan bags. -vibrant brown bags contain 2 dim lavender bags, 4 drab brown bags, 4 vibrant white bags, 4 dim white bags. -light beige bags contain 5 posh gold bags, 4 vibrant olive bags, 4 dotted bronze bags, 5 pale bronze bags. -muted violet bags contain 1 light fuchsia bag, 4 clear gray bags, 2 shiny plum bags, 5 muted plum bags. -dotted yellow bags contain 3 shiny violet bags, 3 vibrant lavender bags, 3 pale cyan bags, 1 dotted gray bag. -drab magenta bags contain 5 light lavender bags. -mirrored red bags contain 4 faded fuchsia bags. -light plum bags contain 2 posh chartreuse bags. -mirrored salmon bags contain 3 drab purple bags, 1 dull coral bag, 2 mirrored teal bags, 4 mirrored gold bags. -dim aqua bags contain 5 bright crimson bags, 2 light fuchsia bags, 4 striped turquoise bags. -plaid cyan bags contain 1 vibrant orange bag, 4 plaid black bags. -mirrored olive bags contain 3 dotted lavender bags, 4 dark tomato bags, 4 dim tan bags. -dotted olive bags contain 5 dark lime bags. -dull orange bags contain 2 muted crimson bags. -clear olive bags contain 1 pale chartreuse bag, 3 faded salmon bags. -vibrant maroon bags contain 2 plaid teal bags. -pale chartreuse bags contain 1 muted gray bag, 4 vibrant fuchsia bags, 2 drab maroon bags. -faded fuchsia bags contain 2 bright olive bags, 2 shiny red bags. -pale brown bags contain 2 dark bronze bags, 4 vibrant aqua bags, 1 dark tan bag. -drab green bags contain 3 light red bags. -vibrant coral bags contain 4 pale tan bags. -drab lime bags contain 5 clear purple bags. -dim salmon bags contain 5 vibrant tomato bags, 4 dotted bronze bags, 1 bright crimson bag. -clear green bags contain 3 vibrant green bags, 3 muted silver bags, 5 clear lime bags. -faded tan bags contain 3 dotted blue bags. -dull gold bags contain 4 clear maroon bags, 5 muted aqua bags. -drab tan bags contain 2 clear blue bags, 5 dull blue bags, 3 dim orange bags. -dark maroon bags contain 4 dim gray bags, 4 dim violet bags, 5 dark black bags. -dim gray bags contain 4 striped blue bags, 5 muted teal bags, 5 dotted lavender bags, 2 dull crimson bags. -shiny indigo bags contain 4 drab plum bags, 4 faded coral bags, 2 wavy maroon bags. -pale indigo bags contain 3 clear lime bags, 4 posh fuchsia bags, 3 bright white bags. -shiny maroon bags contain 2 shiny silver bags, 1 dim brown bag, 3 dim lime bags, 4 mirrored lime bags. -wavy coral bags contain 4 light magenta bags, 4 striped brown bags, 3 vibrant red bags. -dotted purple bags contain 4 faded salmon bags, 4 light fuchsia bags, 4 dim brown bags. -bright indigo bags contain 1 drab bronze bag. -shiny gold bags contain 3 bright turquoise bags, 1 striped purple bag, 5 mirrored white bags, 1 bright teal bag. -drab plum bags contain 1 bright gold bag, 4 dim indigo bags. -bright bronze bags contain 2 shiny olive bags, 2 mirrored lime bags. -dark blue bags contain 3 faded lavender bags. -dull yellow bags contain 1 light white bag, 5 dark teal bags. -clear red bags contain 2 clear gray bags. -faded gray bags contain 1 shiny maroon bag. -dull plum bags contain 3 plaid fuchsia bags, 3 vibrant aqua bags, 4 dim tan bags. -wavy salmon bags contain 4 vibrant tomato bags, 4 muted crimson bags, 1 dotted bronze bag. -shiny white bags contain 2 pale indigo bags, 4 posh gold bags. -light crimson bags contain 3 faded coral bags. -light green bags contain 3 dark blue bags, 3 muted coral bags. -dotted cyan bags contain 4 muted beige bags, 5 faded silver bags. -pale turquoise bags contain 4 pale brown bags. -mirrored lime bags contain no other bags. -bright fuchsia bags contain 1 plaid beige bag, 1 dull cyan bag. -faded aqua bags contain 1 mirrored red bag, 5 striped silver bags, 1 pale magenta bag. -posh white bags contain 4 dark cyan bags. -striped blue bags contain 3 dark brown bags. -bright lavender bags contain 5 mirrored coral bags. -shiny red bags contain 3 wavy violet bags, 5 mirrored aqua bags, 2 plaid maroon bags, 1 striped black bag. -drab maroon bags contain 2 faded salmon bags, 4 dull beige bags, 5 dim cyan bags, 1 muted crimson bag. -plaid brown bags contain 3 mirrored yellow bags, 4 drab magenta bags, 2 light tomato bags. -pale magenta bags contain 2 shiny plum bags, 1 pale aqua bag, 5 dotted indigo bags, 1 pale red bag. -dark teal bags contain 2 dim gray bags, 2 drab beige bags, 4 bright silver bags. -drab turquoise bags contain 5 faded magenta bags. -dark black bags contain 5 striped blue bags, 3 shiny orange bags, 2 pale cyan bags, 5 muted olive bags. -dull salmon bags contain 4 faded chartreuse bags, 3 pale maroon bags, 4 mirrored violet bags, 3 striped blue bags. -dotted silver bags contain 2 wavy violet bags, 2 dim salmon bags, 1 shiny tomato bag, 3 dark turquoise bags. -dull maroon bags contain 3 light coral bags. -mirrored blue bags contain 1 dim brown bag, 2 dim red bags, 1 dim lime bag, 4 striped turquoise bags. -clear blue bags contain 3 dim red bags, 1 dim white bag. -posh orange bags contain 4 dull gray bags, 1 dull aqua bag, 1 drab aqua bag. -clear tomato bags contain 4 dotted magenta bags, 1 dull chartreuse bag, 2 dim aqua bags, 1 dull brown bag. -posh plum bags contain 3 pale crimson bags. -plaid bronze bags contain 5 muted crimson bags, 2 dim salmon bags, 5 faded white bags. -striped purple bags contain no other bags. -striped olive bags contain 5 dark aqua bags, 1 dim cyan bag, 1 striped turquoise bag. -mirrored tan bags contain 2 plaid blue bags. -pale bronze bags contain 1 wavy tomato bag, 2 drab crimson bags, 5 light coral bags, 3 vibrant purple bags. -bright teal bags contain 4 dotted bronze bags, 4 muted olive bags, 4 dim lime bags. -dim purple bags contain 3 muted crimson bags, 1 drab gray bag. -plaid gray bags contain 4 posh salmon bags, 3 vibrant lavender bags, 5 shiny aqua bags. -mirrored black bags contain 2 drab maroon bags, 2 wavy black bags. -striped salmon bags contain 2 striped aqua bags, 1 bright chartreuse bag, 1 faded coral bag. -muted green bags contain 2 faded salmon bags, 3 pale aqua bags, 3 muted gray bags, 1 vibrant olive bag. -wavy aqua bags contain 2 light magenta bags, 2 bright gray bags, 4 light red bags. -shiny chartreuse bags contain 1 posh purple bag, 1 posh tan bag, 5 bright olive bags, 4 mirrored indigo bags. -dim teal bags contain 2 posh tan bags, 1 striped cyan bag, 2 muted lavender bags, 5 wavy lime bags. -clear yellow bags contain 3 dark magenta bags, 4 dotted coral bags. -vibrant plum bags contain 1 mirrored green bag. -shiny fuchsia bags contain 3 muted purple bags, 2 mirrored brown bags, 4 muted tan bags. -dotted gold bags contain 1 light blue bag, 1 vibrant crimson bag, 5 pale aqua bags, 3 wavy salmon bags. -pale coral bags contain 4 vibrant crimson bags, 1 drab coral bag. -drab indigo bags contain 1 dim beige bag, 1 light tomato bag. -plaid maroon bags contain 3 wavy tomato bags, 5 faded blue bags, 4 shiny plum bags. -bright gold bags contain 4 muted lavender bags. -plaid salmon bags contain 3 clear tan bags, 2 dark blue bags, 4 pale olive bags, 3 mirrored beige bags. -shiny brown bags contain 3 posh salmon bags. -dim bronze bags contain 1 light plum bag, 4 faded silver bags, 1 vibrant coral bag. -muted gray bags contain 3 vibrant tomato bags, 2 shiny maroon bags, 5 muted crimson bags, 5 drab brown bags. -shiny aqua bags contain 3 pale bronze bags, 5 dull chartreuse bags, 2 dull cyan bags, 5 posh silver bags. -striped lavender bags contain 4 clear tomato bags. -light indigo bags contain 2 dark silver bags. -clear gold bags contain 4 vibrant olive bags, 4 shiny gold bags, 2 dotted tomato bags, 1 clear magenta bag. -vibrant fuchsia bags contain 5 posh gold bags. -plaid yellow bags contain 2 clear olive bags. -bright violet bags contain 3 mirrored brown bags, 4 wavy bronze bags, 2 mirrored orange bags, 5 dull turquoise bags. -faded crimson bags contain 2 light blue bags, 5 clear silver bags. -faded gold bags contain 1 faded salmon bag, 3 light lavender bags, 4 dotted purple bags. -clear lavender bags contain 3 faded chartreuse bags, 3 clear chartreuse bags, 3 dull turquoise bags. -dim cyan bags contain 3 dim tomato bags, 4 posh fuchsia bags. -dotted turquoise bags contain 3 wavy violet bags, 3 faded magenta bags. -dim chartreuse bags contain 2 muted gray bags, 5 faded salmon bags, 2 pale chartreuse bags. -bright salmon bags contain 5 wavy beige bags. -wavy blue bags contain 3 dim tomato bags, 4 dim cyan bags, 1 dim brown bag. -wavy maroon bags contain 5 dark white bags, 5 plaid gold bags, 2 dotted brown bags, 1 dim coral bag. -plaid turquoise bags contain 2 dark brown bags, 1 vibrant plum bag, 2 shiny green bags. -clear coral bags contain 5 dull chartreuse bags. -light tomato bags contain 2 pale salmon bags, 3 clear cyan bags. -muted salmon bags contain 5 drab turquoise bags, 4 dark gold bags, 2 mirrored green bags. -pale blue bags contain 2 clear silver bags. -dark brown bags contain 1 dim lime bag. \ No newline at end of file diff --git a/2020/day-7.ts b/2020/day-7.ts deleted file mode 100644 index ac569fb..0000000 --- a/2020/day-7.ts +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -interface Container { - color: string; - contains: { - number: number; - color: string; - }[]; -} - -function part1(start: string, containers: Container[]) { - let open: string[] = [start]; - - const containedIn: string[] = []; - - // Walk over the rules, and find our search list - // Then repeat, and find those - while (open.length > 0) { - const processing = open; - open = []; - for (const container of containers) { - if (containedIn.includes(container.color)) { - continue; - } - if (container.contains.some(({ color }) => processing.includes(color))) { - open.push(container.color); - containedIn.push(container.color); - } - } - console.debug(`${processing} bags can be found inside ${open} bags`); - } - console.log(`${containedIn.length} options to contain one ${start} bag: ${containedIn}`); -} - -function part2(start: string, containers: Container[]) { - let open: { color: string, number: number }[] = [{ color: start, number: 1 }]; - - const contents: {[color: string]: number} = {}; - - while (open.length > 0) { - const processing = open; - open = []; - for (const required of processing) { - const container = containers.find(({ color }) => color === required.color)!; - for (const contained of container.contains) { - open.push({ color: contained.color, number: required.number * contained.number }); - contents[contained.color] = (contents[contained.color] || 0) + required.number * contained.number; - } - } - } - console.log(`${Object.values(contents).reduce((result, number) => result + number, 0)} bags contained in one ${start} bag: ${JSON.stringify(contents)}`); -} - -function processInput(input: string) { - const containers: Container[] = []; - - const RULE_RE = /^([a-z ]+) bags contain (no other bags|.*).$/; - const CONTAINMENT_RE = /(\d+) ([a-z ]+) bags?(, )?/g; - - const rl = createInterface(createReadStream(input)); - - rl.on('line', line => { - const match = RULE_RE.exec(line); - if (!match) { - throw new Error(`Failed to parse rule "${line}"`); - } - const [, color, containment] = match; - const container: Container = { - color, - contains: [], - }; - if (containment !== 'no other bags') { - let containmentMatch: RegExpExecArray|null; - while ((containmentMatch = CONTAINMENT_RE.exec(containment)) !== null) { - container.contains.push({ - number: Number(containmentMatch[1]), - color: containmentMatch[2], - }); - } - } - containers.push(container); - }); - rl.on('close', () => { - console.log(`Results for ${input}:`); - - // Part 1: How many options to contain a "shiny gold" bag? - part1('shiny gold', containers); - - // Part 2: What would be inside the "shiny gold" bag (ignoring topology) - part2('shiny gold', containers); - }); -} - -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example.input`); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example-2.input`); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}.input`); \ No newline at end of file diff --git a/2020/day-8-example.input b/2020/day-8-example.input deleted file mode 100644 index 6fee349..0000000 --- a/2020/day-8-example.input +++ /dev/null @@ -1,9 +0,0 @@ -nop +0 -acc +1 -jmp +4 -acc +3 -jmp -3 -acc -99 -acc +1 -jmp -4 -acc +6 \ No newline at end of file diff --git a/2020/day-8.input b/2020/day-8.input deleted file mode 100644 index 37da8aa..0000000 --- a/2020/day-8.input +++ /dev/null @@ -1,613 +0,0 @@ -nop +456 -nop +38 -acc +9 -jmp +153 -acc +15 -nop +560 -jmp +452 -acc +26 -acc +42 -jmp +376 -acc -5 -acc +12 -acc -5 -jmp +15 -jmp +1 -acc -9 -jmp +533 -acc +19 -acc +33 -acc +34 -jmp -6 -nop +404 -nop +140 -acc +0 -jmp +123 -acc +45 -acc +0 -jmp +496 -jmp +487 -acc +9 -acc +34 -jmp +484 -acc +0 -acc -14 -jmp +466 -acc +40 -acc +6 -acc +30 -jmp +444 -nop +386 -jmp +215 -acc +43 -acc +5 -nop -4 -jmp +535 -jmp -13 -acc +3 -acc +7 -acc +49 -acc -1 -jmp +245 -acc +9 -acc +31 -nop +142 -jmp +554 -acc +3 -jmp +493 -nop +399 -jmp +232 -acc -16 -acc +33 -jmp +410 -acc +33 -acc +5 -acc -17 -jmp +272 -acc -3 -acc +37 -jmp +181 -jmp -12 -nop +344 -acc +5 -acc -16 -jmp +290 -nop +530 -acc +15 -acc +3 -jmp +343 -acc +2 -acc +19 -jmp +298 -acc +43 -acc +25 -acc -19 -jmp +439 -acc +43 -acc +45 -acc +20 -jmp +355 -acc +13 -acc +24 -acc -15 -nop +396 -jmp +215 -acc -7 -acc +17 -jmp +441 -acc -8 -acc -19 -jmp +505 -jmp +282 -acc -17 -acc -8 -acc +20 -jmp +359 -acc +26 -acc +14 -acc +47 -acc +3 -jmp +298 -acc +31 -nop +205 -acc +0 -acc +7 -jmp +389 -acc -5 -acc +47 -jmp +94 -acc -13 -jmp +358 -acc -13 -jmp +134 -acc +8 -acc -19 -jmp +312 -acc +43 -acc +17 -jmp +97 -jmp +48 -nop +253 -acc +48 -acc -7 -acc -2 -jmp +23 -acc +26 -acc +14 -acc -14 -acc +17 -jmp +18 -acc +14 -acc +8 -jmp +341 -acc +35 -jmp +227 -acc +15 -acc -7 -jmp -95 -acc -19 -jmp -59 -jmp -31 -acc -6 -acc -4 -acc +24 -jmp +84 -acc -15 -jmp +82 -nop +74 -acc +8 -acc +9 -acc +13 -jmp +194 -jmp +376 -acc +34 -nop -16 -jmp -90 -acc +4 -acc +43 -nop +215 -jmp -147 -acc +0 -acc +11 -acc -15 -acc +23 -jmp +130 -acc +40 -jmp +106 -acc -4 -acc -18 -acc +18 -nop +329 -jmp +230 -acc +19 -nop +172 -acc +43 -jmp +304 -acc +44 -nop +213 -nop +195 -acc +6 -jmp -79 -acc +41 -acc -11 -acc +18 -acc -9 -jmp -25 -acc +27 -acc -6 -acc +31 -jmp -56 -acc +5 -acc +12 -acc +32 -acc +34 -jmp -189 -acc +32 -acc +5 -acc -16 -jmp +301 -nop +108 -nop -108 -jmp -141 -acc -12 -jmp +273 -acc +3 -jmp +140 -acc +7 -acc -11 -acc -17 -nop +194 -jmp -122 -acc -14 -nop +186 -acc +24 -jmp +277 -nop +341 -acc +18 -jmp -64 -acc +45 -acc +42 -jmp +52 -acc +39 -nop +91 -nop -8 -jmp +217 -acc +44 -acc +15 -jmp +72 -acc +24 -jmp -231 -acc -16 -nop +55 -nop +262 -acc +40 -jmp +234 -jmp -14 -acc +31 -nop -177 -acc +40 -jmp +343 -acc -8 -jmp -169 -acc +30 -acc +12 -acc -11 -jmp +41 -acc +9 -acc -9 -jmp +65 -acc +38 -acc +14 -jmp +335 -acc -19 -acc +38 -acc +16 -acc -11 -jmp +230 -jmp -71 -acc +48 -acc -13 -nop -255 -jmp +1 -jmp -220 -acc +2 -jmp +157 -jmp -105 -acc -16 -acc -5 -jmp -196 -acc +30 -jmp +139 -jmp +83 -acc -3 -acc -12 -jmp +254 -jmp -60 -acc +33 -jmp -37 -acc +17 -acc -14 -jmp +93 -nop +178 -acc +38 -acc +47 -jmp -89 -jmp +271 -acc +43 -acc +32 -jmp -240 -acc +26 -acc +32 -acc +30 -nop +284 -jmp +169 -acc -7 -acc +37 -jmp +102 -acc +4 -jmp +86 -jmp -123 -acc +0 -acc -14 -acc +18 -jmp +1 -jmp -5 -jmp -36 -jmp +148 -acc -17 -acc -14 -acc +28 -acc +15 -jmp +79 -jmp -289 -acc +42 -acc -5 -acc +13 -jmp +240 -acc -10 -acc -18 -acc -16 -jmp +103 -acc +21 -jmp +32 -nop +118 -acc +22 -acc -16 -acc +15 -jmp -186 -acc -2 -acc -14 -acc +22 -acc +16 -jmp +73 -acc -6 -jmp -225 -acc -18 -nop +113 -acc +50 -acc -6 -jmp +181 -acc +41 -jmp +1 -nop +92 -acc +23 -jmp +190 -acc +39 -acc +0 -acc +33 -jmp +111 -nop -63 -nop -81 -acc +9 -acc +35 -jmp +50 -acc +11 -jmp -295 -nop +230 -acc +34 -acc +12 -acc +47 -jmp +126 -acc +0 -nop -1 -acc +19 -acc -16 -jmp -360 -acc +29 -acc -2 -jmp -110 -acc +2 -acc +50 -jmp -36 -jmp -107 -jmp +178 -acc -11 -jmp +181 -nop +115 -nop +186 -jmp +95 -jmp +1 -nop +148 -acc +2 -acc +49 -jmp +173 -acc +38 -jmp +178 -acc +28 -acc +6 -acc +15 -jmp +110 -acc +49 -nop +100 -jmp +57 -acc +45 -nop +65 -acc +43 -acc +12 -jmp -272 -jmp -260 -nop +100 -jmp -224 -jmp +142 -jmp +52 -jmp -34 -jmp -110 -acc +35 -nop -112 -jmp +16 -jmp -18 -jmp -157 -jmp +81 -acc +1 -jmp -107 -acc +16 -acc +23 -jmp -255 -acc +22 -jmp +42 -nop +168 -acc +41 -jmp -311 -jmp -163 -jmp +118 -nop +4 -acc +18 -jmp +54 -jmp -414 -nop -181 -acc +10 -acc +23 -jmp -321 -nop -322 -acc -9 -jmp +101 -nop -7 -acc +35 -acc +46 -jmp -312 -nop +64 -nop -386 -jmp -280 -acc +16 -jmp -156 -acc +13 -nop -131 -jmp +1 -jmp -416 -jmp +15 -jmp -94 -jmp -330 -nop +93 -nop -205 -acc +48 -jmp -19 -jmp -70 -nop +21 -acc -5 -acc +19 -jmp +62 -acc +22 -jmp -448 -jmp -77 -acc +26 -acc -2 -jmp +70 -acc -2 -acc +21 -jmp -195 -nop -114 -jmp +107 -acc +37 -acc +6 -jmp -436 -acc +48 -jmp +96 -jmp -121 -acc +0 -jmp -74 -jmp +1 -acc +27 -acc +2 -jmp -279 -acc +7 -acc +0 -jmp +1 -jmp -413 -acc +6 -jmp -180 -acc +18 -acc +10 -jmp -437 -jmp -338 -nop -456 -jmp -463 -acc +1 -nop -54 -jmp -168 -acc +27 -jmp -479 -acc +42 -jmp -408 -jmp +85 -acc -16 -acc +24 -jmp -391 -jmp -206 -nop +8 -jmp +1 -acc +38 -nop -473 -jmp -94 -acc +10 -acc -14 -jmp -425 -acc +17 -nop -208 -acc +39 -jmp -265 -acc +3 -jmp -284 -acc +19 -acc +5 -nop -111 -acc +22 -jmp -309 -acc +12 -acc +39 -jmp -151 -acc +33 -acc -14 -jmp -450 -acc +16 -nop +50 -jmp -188 -acc -13 -acc +15 -acc +4 -jmp -484 -acc +27 -jmp -98 -acc +34 -jmp -120 -jmp -537 -acc +43 -acc -8 -acc -6 -jmp -405 -acc -8 -nop -179 -acc -11 -jmp -264 -acc +24 -jmp -280 -acc -6 -acc +1 -jmp -353 -acc -18 -jmp -58 -acc +1 -acc -7 -acc -2 -acc +44 -jmp -115 -nop -328 -acc +27 -acc +2 -jmp +20 -acc +14 -acc +34 -jmp -460 -nop -445 -acc -9 -acc +24 -acc -11 -jmp -72 -jmp -434 -jmp -370 -acc +35 -acc +43 -acc +45 -acc +44 -jmp -287 -jmp -546 -nop -474 -acc -6 -jmp -357 -nop -163 -nop -218 -nop -342 -jmp -570 -acc +44 -acc +4 -acc +35 -acc +6 -jmp -541 -jmp -274 -acc +48 -acc -18 -jmp -171 -acc -13 -acc -14 -acc +25 -acc +26 -jmp +1 \ No newline at end of file diff --git a/2020/day-8.ts b/2020/day-8.ts deleted file mode 100644 index 01f33c4..0000000 --- a/2020/day-8.ts +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -type Instruction = 'nop'|'acc'|'jmp'; -interface Statement { - instruction: Instruction; - argument: number; -} -type Program = Statement[]; - -const PATCH_TABLE = { - 'nop': 'jmp' as const, - 'acc': 'acc' as const, - 'jmp': 'nop' as const, -}; - -function runProgram(program: Program, patchAt?: number): { acc: number, aborted: boolean, terminated: boolean } { - const executedStatementIndices: number[] = []; - - let acc = 0; - let ip = 0; - let abort = false; - - while (!executedStatementIndices.includes(ip) && ip !== program.length) { - if (ip < 0 || ip > program.length) { - abort = true; - break; - } - - executedStatementIndices.push(ip); - - let { instruction, argument } = program[ip]; - if (ip === patchAt) { - instruction = PATCH_TABLE[instruction]; - } - - switch (instruction) { - case 'nop': - ip++; - break; - case 'acc': - acc += argument; - ip++; - break; - case 'jmp': - ip += argument; - break; - } - } - - return { acc, aborted: abort, terminated: ip === program.length }; -} - -function processInput(input: string) { - const rl = createInterface(createReadStream(input)); - - const program: Statement[] = []; - rl.on('line', line => { - const tmp = line.split(/\s/); - program.push({ - instruction: tmp[0] as Instruction, - argument: Number(tmp[1]), - }); - }); - rl.on('close', () => { - const { acc: result } = runProgram(program); - console.log(`Results for ${input}:`); - console.log(`Unmodified execution: ${result}`); - - for (let patchAt = 0; patchAt < program.length; patchAt++) { - const { acc, aborted, terminated } = runProgram(program, patchAt); - if (terminated) { - console.log(`Patch at ${patchAt} fixes the program: ${acc}`); - break; - } else if (aborted) { - console.log(`Patch at ${patchAt} leads to program abort`); - } - } - }); -} - -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example.input`); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}.input`); diff --git a/2020/day-9-example.input b/2020/day-9-example.input deleted file mode 100644 index 28d66e4..0000000 --- a/2020/day-9-example.input +++ /dev/null @@ -1,20 +0,0 @@ -35 -20 -15 -25 -47 -40 -62 -55 -65 -95 -102 -117 -150 -182 -127 -219 -299 -277 -309 -576 diff --git a/2020/day-9.input b/2020/day-9.input deleted file mode 100644 index 077d244..0000000 --- a/2020/day-9.input +++ /dev/null @@ -1,1000 +0,0 @@ -24 -27 -31 -3 -26 -29 -14 -16 -25 -15 -32 -6 -41 -22 -2 -1 -12 -8 -7 -4 -48 -13 -47 -34 -5 -18 -33 -11 -45 -3 -9 -10 -14 -21 -16 -15 -17 -20 -19 -6 -22 -23 -12 -8 -7 -26 -24 -13 -25 -27 -29 -18 -28 -35 -42 -30 -31 -32 -14 -33 -21 -46 -36 -37 -15 -19 -40 -63 -20 -22 -38 -67 -34 -39 -43 -41 -53 -29 -44 -45 -76 -84 -50 -35 -55 -42 -56 -74 -48 -73 -49 -58 -88 -51 -63 -64 -69 -68 -70 -71 -77 -78 -86 -85 -95 -90 -114 -138 -83 -91 -136 -206 -153 -97 -121 -119 -109 -115 -120 -131 -139 -137 -141 -207 -181 -155 -163 -173 -176 -174 -210 -180 -305 -192 -212 -369 -303 -228 -206 -224 -234 -229 -317 -251 -280 -350 -278 -296 -318 -379 -328 -336 -382 -497 -354 -372 -386 -440 -398 -418 -524 -587 -479 -430 -453 -707 -696 -812 -697 -664 -596 -574 -771 -722 -682 -1175 -690 -758 -1140 -726 -826 -784 -816 -897 -992 -883 -1066 -909 -1112 -1179 -1170 -1296 -1318 -2088 -1238 -1380 -1300 -1995 -1372 -1466 -1416 -1448 -1896 -1510 -1542 -2112 -1986 -1725 -1780 -3008 -1949 -1975 -3412 -2282 -2721 -2408 -2734 -2828 -2864 -3018 -3459 -2672 -2788 -2820 -2882 -2958 -3228 -3322 -4231 -3267 -4670 -3505 -3674 -4957 -4257 -4683 -4383 -5522 -4690 -5129 -5080 -5406 -5460 -5492 -5554 -6247 -8175 -5608 -10162 -8195 -9663 -6495 -6589 -6772 -7888 -10278 -8803 -9763 -8640 -13803 -9073 -10928 -10182 -9770 -10540 -10486 -10866 -10952 -11046 -14411 -14422 -12103 -17541 -16981 -18573 -13084 -18918 -24897 -14660 -16528 -17876 -17443 -17713 -18843 -19255 -19559 -19952 -24908 -20310 -35824 -21352 -25363 -24036 -23149 -31188 -25187 -26763 -27744 -29612 -39565 -38870 -40023 -32103 -57441 -38795 -38814 -35156 -36968 -38098 -39207 -39511 -44501 -41662 -43459 -64233 -91977 -47185 -65558 -48336 -51950 -54799 -66614 -90745 -82970 -71310 -76912 -67259 -69071 -74667 -79760 -72124 -73254 -86696 -134559 -86163 -120357 -85121 -115595 -109017 -95521 -146374 -99135 -100286 -103135 -106749 -121413 -140513 -136330 -138569 -139383 -141195 -172859 -142325 -145378 -151884 -157245 -171817 -186982 -198656 -171284 -237704 -180642 -202270 -194656 -195807 -243648 -240330 -305405 -209884 -276843 -274899 -310386 -275713 -279764 -302623 -483245 -287703 -393312 -297262 -309129 -367091 -471520 -412154 -375298 -455541 -376449 -382912 -668211 -470706 -493069 -450214 -484783 -585285 -486727 -977852 -550612 -555477 -578336 -590326 -584965 -596832 -606391 -673711 -664353 -1135059 -957433 -788603 -942268 -973281 -1005691 -759361 -1021318 -920920 -934997 -1378929 -1476397 -971510 -1037339 -1042204 -1796700 -1963894 -1133813 -1163301 -1175291 -1344326 -1385435 -1280102 -1338064 -1423714 -1934652 -2482088 -1760113 -1730871 -2285793 -1680281 -1972336 -2306355 -2421133 -1906507 -2008849 -2013714 -3844847 -2171152 -2761778 -3586788 -2501365 -2297114 -2338592 -3330221 -2618166 -2665537 -3010973 -5061092 -3103995 -3411152 -3440394 -3490984 -4269450 -4310828 -3652617 -3878843 -4807720 -3915356 -3920221 -4022563 -6889816 -4468266 -8460337 -6088153 -6806858 -4635706 -4915280 -4956758 -6931378 -6270783 -8936320 -6114968 -6515147 -6544389 -6851546 -7093011 -7143601 -7675180 -7531460 -7572838 -7794199 -8383622 -7835577 -7942784 -8490829 -11275124 -9103972 -11150853 -9550986 -9592464 -9872038 -11227541 -11071726 -12385751 -12630115 -14768191 -13658748 -13944557 -13395935 -13995147 -15248018 -14818781 -15104298 -19658746 -20778527 -18696436 -16219199 -15778361 -23309610 -23546133 -18654958 -18976010 -20622712 -22502153 -26625262 -20943764 -31323497 -36048062 -25015866 -28477529 -27054683 -27340492 -27391082 -28214716 -29923079 -39319148 -30882659 -31997560 -39640200 -34433319 -34474797 -61865879 -37630968 -39277670 -45995450 -39598722 -39919774 -45959630 -43445917 -64397876 -47998447 -54445765 -53230582 -59097375 -62648035 -68134490 -60805738 -76950116 -58137795 -69563279 -62880219 -77550742 -73710989 -68908116 -106136242 -72105765 -76908638 -121018014 -79197444 -106093952 -79518496 -83365691 -145084606 -96676499 -115878617 -120785830 -107676347 -111368377 -151624261 -118943533 -136591208 -127045911 -134985984 -127701074 -154459380 -131788335 -141013881 -142619105 -148426612 -156427134 -149014403 -281505291 -158715940 -180042190 -189459643 -239295604 -191042038 -228464834 -236664447 -300828020 -219044724 -226619880 -298985723 -255534741 -245989444 -373035355 -290504275 -259489409 -268714955 -272802216 -280802738 -283632986 -291045717 -394416056 -305441537 -307730343 -371084228 -338758130 -599549062 -380501681 -573630236 -410086762 -501267050 -527168722 -519872744 -528204364 -517665597 -373803594 -586244275 -574156492 -532291625 -540292147 -578243753 -1028435772 -685943218 -856423727 -574678703 -596487254 -613171880 -644199667 -646488473 -709842358 -986975474 -1101325214 -906095219 -1106448117 -937255484 -914095741 -891469191 -1145463505 -1049957222 -947960086 -948482297 -1152400245 -1072583772 -1106970328 -1118535900 -1299115098 -1600147354 -1510582995 -1828724675 -1221167176 -1209659134 -1323014238 -2220425353 -1594970770 -2066495986 -1820190960 -1797564410 -1805564932 -1998439519 -1851351225 -1839429277 -2355122639 -2169649473 -3405079861 -2542930856 -2021066069 -2662983240 -2179554100 -2225506228 -2328195034 -3219606695 -2821314530 -2430826310 -2532673372 -3060596453 -2804629904 -4702322845 -3392535180 -3415161730 -3617755370 -3603129342 -6150428742 -3644994209 -4167624311 -3860495346 -4009078750 -4190715542 -4200620169 -5337303276 -5865226357 -5593269825 -7921464859 -4405060328 -7032917100 -5845988040 -5252140840 -4963499682 -5491422763 -6135802714 -9136416972 -6219791634 -9692042932 -7770753653 -7018291072 -7220884712 -7248123551 -7505489555 -7654072959 -11223632642 -7869574096 -8199794292 -8391335711 -8605680497 -10556769507 -12509713835 -13364023478 -10454922445 -9368560010 -11337410803 -10215640522 -10743563603 -11099302396 -11711214397 -12355594348 -13238082706 -13440676346 -14672364031 -26678759052 -14469008263 -14726374267 -18613137699 -15159562514 -19911008689 -16069368388 -22571234870 -21724154358 -16997016208 -17974240507 -19584200532 -19823482455 -20112123613 -21314942918 -20467862406 -27406779191 -23656316868 -21842865999 -22810516793 -28113040377 -25593677054 -27909684609 -28167050613 -36515230030 -29195382530 -35653568920 -34310574799 -41753874688 -31228930902 -48279174226 -48580902783 -44534671151 -65410191556 -48377547015 -37558441039 -40052062938 -77474556756 -40579986019 -50977567406 -42310728405 -44653382792 -70220413014 -47436543053 -67744160932 -53503361663 -54789059584 -56076735222 -84732292565 -60424313432 -63505957329 -65539505701 -93030929807 -68787371941 -71280993840 -77610503977 -78138427058 -79869169444 -80632048957 -82211823831 -82890714424 -155612983814 -162342796542 -117656956067 -175242753638 -105077696224 -92089925845 -107860856485 -242986914570 -108292421247 -119042867364 -150999195772 -154171708264 -330855737452 -143677932759 -129045463030 -136820499541 -140068365781 -238503698238 -148891497817 -165102538255 -162080993275 -160501218401 -162843872788 -270203653027 -201933581788 -225949377314 -197167622069 -199950782330 -224120563588 -200382347092 -211132793209 -285711997358 -227335288611 -291889335818 -616567734810 -265865962571 -283217171294 -269113828811 -272723395789 -276888865322 -493822917606 -472137234815 -324924866063 -309392716218 -432284646302 -322582211676 -323345091189 -360011494857 -397118404399 -467799544359 -400333129422 -397549969161 -411083575539 -424502910680 -411515140301 -546002694133 -493201251182 -496449117422 -608142037357 -669404211075 -595305607465 -541837224600 -549612261111 -582116112007 -600233956511 -632737807407 -648269957252 -682593706533 -631974927894 -720132180837 -645927302865 -893999086583 -1019657177658 -1093907121755 -868132673781 -1328274218194 -809065109462 -822598715840 -836018050981 -904716391483 -1078565229429 -1315437788302 -1038286342022 -1131728373118 -1091449485711 -1123953336607 -1214853919414 -1149846217622 -1264709818540 -1232208884405 -1264712735301 -1454573643734 -1536691319377 -1940793482580 -1529197290299 -1454992412327 -2151385550776 -2353724130324 -2397329964080 -1631663825302 -3808297774058 -1645083160443 -3851903607814 -2116851571451 -1943002733505 -2578945748934 -2129735827733 -2215402822318 -2223177858829 -2877292044848 -2273799554229 -2364700137036 -2719705147628 -2793910025600 -2496921619706 -3996363962338 -2984189702626 -2991683731704 -6843587339518 -3086656237629 -3606377963103 -3276746985745 -3761399653035 -3574666558807 -3588085893948 -3761934731894 -3774818988176 -4708681576667 -4836556719079 -4072738561238 -5855692734679 -5374213664554 -4438580681147 -4496977413058 -5550546539974 -4638499691265 -5481111322332 -5216626767334 -5290831645306 -6661322796436 -5975873434330 -6070845940255 -6363403223374 -6674742131577 -6693034200732 -8103355376161 -6851413544552 -7162752452755 -11601333133902 -8483500564843 -9243046054226 -7847557549414 -11266705079636 -9077080372412 -8569715974296 -11406239274653 -8935558094205 -9135477104323 -10614373125595 -9855126458599 -9929331336571 -14352103871657 -11654234868680 -17307407326327 -13526155676129 -12046719374585 -14174201316416 -13038145354951 -17646796346708 -13544447745284 -19098172512825 -14014165997307 -15010310002169 -25440906396052 -16331058114257 -16417273523710 -20731315241092 -17505274068501 -17705193078619 -18071035198528 -18790684552804 -18864889430776 -18990603562922 -38038722567419 -19784457795170 -23455487012700 -25084864729536 -23700954243265 -28554757747453 -25572875050714 -31109180553479 -31828829907755 -31191244091992 -39455072393359 -31719359075926 -29024475999476 -32515584070670 -31341368116426 -34036251192876 -32748331637967 -33922547592211 -35210467147120 -35576309267029 -63939575729959 -36861719751332 \ No newline at end of file diff --git a/2020/day-9.ts b/2020/day-9.ts deleted file mode 100644 index e45f4e7..0000000 --- a/2020/day-9.ts +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -function isValid(window: number[], n: number): boolean { - for (let i = 0; i < window.length; i++) { - for (let j = 0; j < window.length; j++) { - if (i === j) { - continue; - } - if (window[i] + window[j] === n) { - return true; - } - } - } - return false; -} - -function findFirstInvalid(numbers: number[], windowLength: number): { index: number, value: number } { - for (let index = windowLength; index < numbers.length; index++) { - const window = numbers.slice(index - windowLength, index); - if (!isValid(window, numbers[index])) { - return { index, value: numbers[index] }; - } - } - throw new Error('All valid!'); -} - -function findWeakness(numbers: number[], value: number): { firstIndex: number, lastIndex: number, weakness: number } { - // XXX: This really smells like a faster string-search algorithm, dynamic programming or such similar to levenshtein, might work - // quite well here. - for (let firstIndex = 0; firstIndex < numbers.length; firstIndex++) { - // Try summing from here until we find a value bigger than number - const firstValue = numbers[firstIndex]; - let sum = firstValue; - let lastIndex = firstIndex; - let smallest = firstValue; - let largest = firstValue; - do { - const v = numbers[++lastIndex]; - sum += v; - if (v < smallest) { - smallest = v; - } else if (v > largest) { - largest = v; - } - } while (sum < value); - if (sum === value) { - return { firstIndex, lastIndex, weakness: smallest + largest }; - } - } - throw new Error('Cannot find weakness'); -} - -function processInput(input: string, preamble: number) { - const rl = createInterface(createReadStream(input)); - - // Collect everything, rather than immediately processing things to simplify - // the code to drive readline. - const numbers: number[] = []; - rl.on('line', line => { - const n = Number(line); - numbers.push(n); - }); - rl.on('close', () => { - // Report results for this input - console.log(`Results for ${input}:`); - const { index, value } = findFirstInvalid(numbers, preamble); - console.log(`Entry at position ${index} is invalid: ${value}`); - - const { firstIndex, lastIndex, weakness } = findWeakness(numbers, value); - console.log(`Entries between ${firstIndex} and ${lastIndex} (${numbers.slice(firstIndex, lastIndex + 1)}) form the weakness of ${weakness}`); - }); -} - -processInput(`${basename(process.argv[1], extname(process.argv[1]))}-example.input`, 5); -processInput(`${basename(process.argv[1], extname(process.argv[1]))}.input`, 25); \ No newline at end of file diff --git a/2021/day-1-example.input b/2021/day-1-example.input deleted file mode 100644 index 59dad67..0000000 --- a/2021/day-1-example.input +++ /dev/null @@ -1,10 +0,0 @@ -199 -200 -208 -210 -200 -207 -240 -269 -260 -263 \ No newline at end of file diff --git a/2021/day-1.input b/2021/day-1.input deleted file mode 100644 index 33b623c..0000000 --- a/2021/day-1.input +++ /dev/null @@ -1,2000 +0,0 @@ -140 -154 -165 -150 -151 -161 -172 -174 -166 -168 -176 -191 -192 -189 -190 -191 -202 -203 -206 -207 -167 -179 -204 -206 -208 -209 -216 -198 -200 -207 -217 -218 -223 -227 -228 -243 -241 -246 -278 -255 -256 -273 -295 -291 -288 -290 -303 -325 -301 -292 -291 -309 -313 -315 -319 -339 -340 -327 -336 -335 -340 -331 -334 -316 -317 -323 -324 -323 -312 -298 -291 -285 -288 -266 -267 -266 -258 -259 -257 -259 -250 -265 -270 -267 -271 -272 -277 -281 -277 -284 -291 -283 -284 -291 -292 -278 -285 -296 -294 -297 -298 -301 -300 -311 -310 -322 -320 -337 -334 -333 -331 -317 -323 -358 -362 -364 -371 -383 -424 -427 -438 -443 -441 -445 -444 -440 -458 -460 -459 -457 -455 -446 -440 -439 -438 -430 -422 -424 -438 -449 -450 -451 -443 -459 -458 -479 -473 -471 -478 -496 -498 -488 -512 -513 -523 -545 -544 -543 -539 -540 -553 -554 -553 -561 -565 -572 -576 -584 -586 -591 -603 -585 -600 -601 -599 -596 -587 -586 -587 -588 -598 -601 -599 -596 -588 -589 -595 -588 -586 -591 -598 -595 -597 -616 -615 -599 -598 -576 -570 -573 -599 -600 -601 -602 -604 -605 -617 -608 -607 -606 -607 -605 -604 -603 -601 -602 -584 -590 -597 -596 -600 -583 -579 -582 -576 -580 -583 -581 -582 -558 -566 -562 -581 -589 -570 -571 -566 -562 -564 -565 -567 -564 -557 -565 -566 -562 -564 -567 -568 -570 -554 -546 -548 -511 -510 -509 -507 -500 -513 -510 -513 -500 -502 -508 -527 -531 -539 -538 -545 -546 -548 -555 -557 -558 -561 -566 -567 -571 -570 -605 -627 -625 -615 -617 -588 -597 -599 -598 -609 -612 -611 -615 -617 -618 -630 -622 -619 -627 -674 -691 -695 -715 -734 -736 -737 -739 -753 -751 -759 -762 -732 -709 -711 -730 -733 -729 -746 -752 -755 -756 -791 -792 -793 -790 -786 -808 -811 -844 -834 -846 -820 -821 -838 -842 -844 -835 -840 -843 -844 -836 -837 -841 -843 -852 -863 -865 -870 -868 -863 -865 -868 -875 -886 -904 -909 -917 -905 -906 -905 -920 -919 -917 -911 -924 -899 -900 -915 -923 -940 -941 -921 -922 -896 -908 -911 -893 -892 -912 -896 -900 -882 -884 -901 -902 -901 -907 -886 -889 -888 -898 -899 -896 -899 -883 -900 -893 -929 -907 -911 -916 -910 -912 -906 -911 -915 -920 -921 -923 -921 -922 -905 -923 -922 -938 -939 -941 -940 -931 -960 -966 -973 -986 -988 -1008 -1016 -1014 -987 -993 -1004 -1006 -1004 -1024 -1031 -1032 -1034 -1025 -1022 -1008 -1007 -1010 -1009 -997 -1002 -1007 -1010 -1018 -1014 -1016 -1023 -1031 -1032 -1048 -1049 -1056 -1055 -1064 -1065 -1084 -1081 -1084 -1088 -1090 -1109 -1115 -1144 -1146 -1144 -1142 -1143 -1160 -1158 -1163 -1167 -1183 -1184 -1195 -1182 -1181 -1169 -1181 -1175 -1188 -1187 -1188 -1189 -1187 -1195 -1196 -1197 -1216 -1215 -1223 -1222 -1209 -1218 -1223 -1222 -1225 -1196 -1193 -1198 -1200 -1208 -1207 -1216 -1202 -1197 -1172 -1164 -1178 -1179 -1167 -1177 -1178 -1175 -1178 -1191 -1198 -1200 -1208 -1212 -1215 -1225 -1233 -1240 -1243 -1235 -1237 -1244 -1245 -1248 -1249 -1251 -1250 -1256 -1261 -1262 -1244 -1250 -1240 -1234 -1225 -1229 -1216 -1213 -1214 -1206 -1209 -1211 -1205 -1228 -1230 -1232 -1233 -1226 -1216 -1204 -1194 -1196 -1165 -1176 -1186 -1198 -1195 -1204 -1218 -1216 -1219 -1220 -1225 -1229 -1227 -1231 -1241 -1244 -1241 -1249 -1248 -1253 -1254 -1247 -1248 -1249 -1258 -1266 -1270 -1269 -1283 -1298 -1295 -1306 -1309 -1330 -1335 -1339 -1326 -1327 -1291 -1302 -1301 -1313 -1314 -1315 -1318 -1315 -1316 -1315 -1338 -1336 -1341 -1347 -1343 -1368 -1374 -1377 -1378 -1383 -1384 -1367 -1368 -1367 -1378 -1371 -1372 -1373 -1365 -1367 -1366 -1369 -1365 -1367 -1361 -1360 -1368 -1366 -1363 -1366 -1374 -1380 -1364 -1339 -1341 -1340 -1339 -1340 -1341 -1348 -1356 -1358 -1359 -1351 -1356 -1345 -1322 -1323 -1324 -1325 -1326 -1336 -1335 -1331 -1330 -1339 -1331 -1329 -1346 -1343 -1350 -1357 -1358 -1334 -1336 -1335 -1338 -1348 -1346 -1363 -1365 -1368 -1365 -1386 -1383 -1381 -1383 -1379 -1386 -1381 -1384 -1378 -1379 -1372 -1389 -1393 -1389 -1414 -1415 -1414 -1405 -1417 -1418 -1415 -1427 -1429 -1428 -1447 -1430 -1426 -1425 -1410 -1412 -1413 -1427 -1424 -1413 -1401 -1402 -1423 -1431 -1436 -1440 -1447 -1446 -1447 -1446 -1447 -1446 -1451 -1450 -1451 -1450 -1446 -1451 -1456 -1453 -1456 -1459 -1490 -1494 -1493 -1502 -1504 -1524 -1523 -1522 -1539 -1546 -1545 -1552 -1554 -1555 -1557 -1563 -1562 -1566 -1567 -1566 -1567 -1566 -1565 -1568 -1570 -1572 -1573 -1586 -1588 -1590 -1591 -1589 -1607 -1608 -1595 -1596 -1595 -1594 -1599 -1604 -1612 -1608 -1609 -1606 -1603 -1602 -1601 -1613 -1597 -1598 -1585 -1604 -1625 -1626 -1627 -1634 -1636 -1637 -1642 -1637 -1638 -1630 -1632 -1631 -1630 -1639 -1640 -1668 -1647 -1663 -1668 -1646 -1653 -1665 -1667 -1668 -1671 -1679 -1673 -1678 -1679 -1684 -1677 -1678 -1688 -1687 -1686 -1691 -1697 -1699 -1705 -1717 -1685 -1708 -1707 -1708 -1706 -1709 -1699 -1700 -1699 -1710 -1709 -1708 -1714 -1728 -1721 -1715 -1717 -1694 -1706 -1720 -1722 -1730 -1722 -1728 -1730 -1737 -1755 -1763 -1747 -1742 -1743 -1727 -1736 -1730 -1742 -1744 -1734 -1726 -1707 -1720 -1719 -1725 -1683 -1682 -1683 -1688 -1682 -1681 -1682 -1684 -1689 -1649 -1650 -1652 -1655 -1662 -1665 -1666 -1667 -1689 -1684 -1677 -1678 -1667 -1666 -1670 -1672 -1670 -1675 -1672 -1659 -1660 -1689 -1688 -1691 -1696 -1687 -1689 -1688 -1689 -1690 -1695 -1705 -1710 -1713 -1715 -1706 -1703 -1707 -1683 -1677 -1670 -1664 -1675 -1676 -1681 -1682 -1679 -1673 -1678 -1668 -1685 -1703 -1716 -1712 -1709 -1715 -1720 -1730 -1735 -1741 -1754 -1740 -1749 -1750 -1753 -1746 -1753 -1768 -1780 -1781 -1818 -1821 -1831 -1830 -1838 -1839 -1838 -1843 -1829 -1833 -1835 -1847 -1845 -1849 -1850 -1852 -1828 -1830 -1836 -1839 -1855 -1857 -1837 -1838 -1843 -1830 -1825 -1848 -1838 -1840 -1843 -1831 -1813 -1816 -1815 -1810 -1809 -1817 -1816 -1818 -1806 -1802 -1803 -1807 -1805 -1770 -1759 -1757 -1756 -1759 -1751 -1752 -1753 -1747 -1755 -1762 -1766 -1767 -1777 -1778 -1772 -1784 -1783 -1789 -1795 -1797 -1823 -1824 -1820 -1823 -1824 -1843 -1866 -1868 -1864 -1860 -1861 -1864 -1862 -1849 -1850 -1862 -1860 -1862 -1863 -1862 -1870 -1893 -1896 -1897 -1888 -1889 -1913 -1914 -1911 -1924 -1928 -1943 -1958 -1957 -1951 -1939 -1929 -1931 -1930 -1928 -1930 -1946 -1954 -1955 -1944 -1934 -1935 -1950 -1957 -1956 -1957 -1958 -1952 -1951 -1954 -1953 -1941 -1949 -1950 -1968 -1961 -1960 -1955 -1949 -1946 -1918 -1919 -1920 -1933 -1934 -1936 -1937 -1942 -1913 -1919 -1920 -1921 -1925 -1924 -1925 -1932 -1935 -1937 -1927 -1913 -1916 -1922 -1906 -1907 -1908 -1901 -1897 -1901 -1899 -1900 -1902 -1903 -1896 -1901 -1904 -1909 -1901 -1912 -1914 -1910 -1913 -1914 -1915 -1917 -1921 -1922 -1920 -1919 -1912 -1909 -1911 -1908 -1909 -1950 -1953 -1983 -1989 -1993 -1992 -1994 -1997 -1980 -1990 -1991 -2011 -2016 -2015 -2026 -2030 -2033 -2044 -2039 -2040 -2042 -2044 -2053 -2054 -2033 -2030 -2029 -2030 -2013 -2016 -2027 -2021 -2017 -2018 -2011 -2009 -2008 -2007 -2004 -1994 -1992 -1973 -1974 -1969 -1963 -1968 -1969 -1967 -1980 -1981 -1984 -1981 -1977 -1982 -2002 -2007 -2003 -2000 -2019 -2013 -2014 -2017 -2054 -2081 -2079 -2077 -2078 -2064 -2063 -2065 -2061 -2051 -2069 -2095 -2093 -2098 -2095 -2084 -2085 -2087 -2088 -2082 -2080 -2081 -2082 -2079 -2068 -2072 -2073 -2092 -2096 -2097 -2078 -2083 -2090 -2081 -2093 -2077 -2084 -2087 -2074 -2075 -2061 -2052 -2058 -2065 -2052 -2053 -2055 -2067 -2063 -2072 -2077 -2075 -2081 -2082 -2089 -2109 -2110 -2107 -2102 -2098 -2085 -2089 -2091 -2097 -2087 -2077 -2073 -2079 -2074 -2076 -2077 -2078 -2061 -2076 -2077 -2080 -2091 -2074 -2075 -2080 -2085 -2090 -2095 -2103 -2106 -2108 -2116 -2120 -2128 -2129 -2130 -2146 -2153 -2166 -2165 -2169 -2173 -2158 -2149 -2154 -2162 -2161 -2162 -2164 -2165 -2166 -2167 -2159 -2180 -2181 -2177 -2193 -2208 -2206 -2214 -2216 -2239 -2218 -2219 -2228 -2203 -2204 -2212 -2211 -2219 -2227 -2228 -2229 -2230 -2231 -2228 -2237 -2236 -2245 -2246 -2244 -2252 -2262 -2260 -2270 -2269 -2270 -2289 -2290 -2313 -2289 -2292 -2293 -2295 -2300 -2301 -2302 -2314 -2317 -2329 -2330 -2310 -2313 -2314 -2293 -2294 -2299 -2300 -2323 -2325 -2320 -2317 -2323 -2310 -2296 -2297 -2293 -2320 -2310 -2311 -2315 -2319 -2320 -2328 -2338 -2345 -2349 -2370 -2374 -2376 -2375 -2370 -2372 -2373 -2374 -2377 -2388 -2392 -2355 -2361 -2397 -2398 -2386 -2400 -2398 -2399 -2383 -2384 -2394 -2397 -2400 -2401 -2406 -2409 -2411 -2426 -2447 -2441 -2443 -2418 -2417 -2418 -2407 -2408 -2409 -2423 -2420 -2394 -2393 -2401 -2410 -2404 -2423 -2429 -2431 -2432 -2405 -2406 -2407 -2400 -2401 -2390 -2389 -2391 -2387 -2388 -2399 -2415 -2416 -2421 -2420 -2424 -2432 -2436 -2419 -2422 -2421 -2411 -2426 -2427 -2441 -2433 -2439 -2431 -2429 -2431 -2434 -2442 -2456 -2439 -2440 -2443 -2452 -2453 -2456 -2459 -2458 -2470 -2471 -2470 -2471 -2474 -2475 -2480 -2477 -2473 -2472 -2501 -2500 -2507 -2516 -2530 -2548 -2557 -2589 -2587 -2589 -2593 -2598 -2600 -2603 -2605 -2604 -2605 -2606 -2614 -2615 -2623 -2626 -2638 -2632 -2635 -2641 -2642 -2641 -2660 -2661 -2685 -2683 -2689 -2693 -2674 -2676 -2698 -2727 -2725 -2716 -2735 -2729 -2753 -2756 -2765 -2766 -2774 -2775 -2774 -2775 -2779 -2785 -2806 -2803 -2813 -2803 -2801 -2802 -2781 -2782 -2780 -2785 -2788 -2784 -2779 -2755 -2758 -2759 -2773 -2774 -2776 -2779 -2802 -2787 -2781 -2785 -2779 -2778 -2776 -2779 -2781 -2777 -2772 -2771 -2756 -2758 -2764 -2776 -2775 -2768 -2771 -2769 -2764 -2765 -2764 -2754 -2755 -2753 -2767 -2770 -2774 -2783 -2782 -2783 -2778 -2782 -2784 -2775 -2778 -2774 -2773 -2774 -2776 -2784 -2796 -2797 -2796 -2807 -2798 -2799 -2800 -2801 -2802 -2805 -2817 -2818 -2809 -2819 -2818 -2800 -2796 -2795 -2796 -2797 -2799 -2805 -2833 -2835 -2804 -2809 -2810 -2784 -2806 -2815 -2824 -2849 -2837 -2832 -2831 -2839 -2841 -2843 -2844 -2856 -2855 -2858 -2857 -2852 -2858 -2850 -2845 -2841 -2831 -2825 -2818 -2820 -2819 -2822 -2831 -2832 -2825 -2824 -2821 -2822 -2807 -2808 -2810 -2823 -2811 -2821 -2813 -2822 -2810 -2818 -2824 -2837 -2851 -2852 -2835 -2831 -2832 -2820 -2801 -2802 -2803 -2812 -2840 -2838 -2841 -2843 -2846 -2854 -2856 -2857 -2886 -2900 -2906 -2907 -2902 -2910 -2918 -2925 -2926 -2924 -2925 -2918 -2925 -2913 -2912 -2932 -2938 -2936 -2941 -2948 -2950 -2951 -2954 -2958 -2961 -2966 -2995 -2999 -3005 -3017 -3025 -3024 -3025 -3027 -3030 -3034 -3030 -3032 -3035 -3034 -3033 -3032 -3033 -3024 -3027 -3028 -3029 -3030 -3034 -3064 -3050 -3056 -3053 -3065 -3072 -3067 -3065 -3068 -3086 -3089 -3100 -3109 -3104 -3105 -3108 -3098 -3105 -3110 -3111 -3129 -3137 -3138 -3121 -3113 -3125 -3133 -3135 -3137 -3143 -3133 -3134 -3133 -3137 -3145 -3164 -3169 -3170 -3184 -3165 -3168 -3166 -3159 -3158 -3165 -3162 -3145 -3133 -3134 -3149 -3153 -3151 -3158 -3160 -3161 -3164 -3165 -3159 -3145 -3146 -3147 -3148 -3131 -3140 -3148 -3144 -3167 -3149 -3150 -3142 -3115 -3129 -3134 -3136 -3141 -3164 -3165 -3162 -3161 -3169 -3170 -3169 -3171 -3167 -3173 -3181 -3186 -3187 -3186 -3190 -3191 -3193 -3194 -3204 -3205 -3222 -3221 -3231 -3232 -3233 -3234 -3231 -3240 -3246 -3258 -3260 -3277 -3278 -3274 -3275 -3273 -3276 -3270 -3290 -3292 -3300 -3320 -3324 -3323 -3321 -3320 -3301 -3308 -3305 -3306 -3301 -3309 -3306 -3327 -3334 -3333 -3338 -3339 -3341 -3342 -3353 -3325 -3333 -3342 -3329 -3330 -3323 -3320 -3334 -3347 -3336 -3324 -3330 -3328 -3324 -3321 -3322 -3325 -3311 -3313 -3311 -3340 -3342 -3346 -3350 -3351 -3334 -3360 -3344 -3347 -3341 -3344 -3358 -3350 -3344 -3354 -3349 -3363 -3380 -3372 -3375 -3369 -3365 -3376 -3375 -3381 -3380 -3385 -3405 -3407 -3408 -3411 -3406 -3408 -3410 -3414 -3438 -3459 -3456 -3457 -3449 -3452 -3455 -3460 -3465 -3466 -3468 -3466 -3465 -3466 -3467 -3472 -3468 -3462 -3489 -3492 -3494 -3470 -3466 -3478 -3494 -3481 -3497 -3498 -3499 -3500 -3502 -3492 -3489 -3502 -3503 -3518 -3523 -3526 -3534 -3536 -3542 -3545 -3548 -3549 -3551 -3554 -3546 -3570 -3584 -3585 -3552 -3551 -3558 -3559 -3560 -3558 -3551 -3556 -3549 -3541 -3544 -3559 -3577 -3581 -3562 -3564 -3565 -3547 -3551 -3552 -3557 -3569 -3571 -3563 -3575 -3587 -3591 -3595 -3596 \ No newline at end of file diff --git a/2021/day-1.ts b/2021/day-1.ts deleted file mode 100644 index 979406a..0000000 --- a/2021/day-1.ts +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -function processInput(input: string) { - const rl = createInterface(createReadStream(input)); - - const windowSize = 3; - const window: number[] = []; - let increases: number = 0; - rl.on('line', line => { - const value = Number(line); - let lastSum; - if (window.length === windowSize) { - lastSum = window.reduce((s, v) => s + v, 0); - window.splice(0, 1); - } - window.push(value); - if (typeof lastSum !== 'undefined') { - // We removed one, and we added one -- so window.length is still equal to the window size. - const sum = window.reduce((s, v) => s + v, 0); - if (sum > lastSum) { - increases++; - } - } - }); - rl.on('close', () => { - console.log(`Results for ${input}: ${increases} increases`); - }); -} - -const INPUT_SPECS = [ - '-example', - '', -]; -for (const inputSpec of INPUT_SPECS) { - const inputFile = `${basename(process.argv[1], extname(process.argv[1]))}${inputSpec}.input`; - processInput(inputFile); -} diff --git a/2021/day-10-example.input b/2021/day-10-example.input deleted file mode 100644 index b1518d9..0000000 --- a/2021/day-10-example.input +++ /dev/null @@ -1,10 +0,0 @@ -[({(<(())[]>[[{[]{<()<>> -[(()[<>])]({[<{<<[]>>( -{([(<{}[<>[]}>{[]{[(<()> -(((({<>}<{<{<>}{[]{[]{} -[[<[([]))<([[{}[[()]]] -[{[{({}]{}}([{[{{{}}([] -{<[[]]>}<{[{[{[]{()[[[] -[<(<(<(<{}))><([]([]() -<{([([[(<>()){}]>(<<{{ -<{([{{}}[<[[[<>{}]]]>[]] diff --git a/2021/day-10.input b/2021/day-10.input deleted file mode 100644 index aa8d39d..0000000 --- a/2021/day-10.input +++ /dev/null @@ -1,110 +0,0 @@ -([[<[[[[<{((([<>][{}<>])[<<>{}>[{}[]]])((({}())({}{}))<<()<>>([]<>)]))<<[[[][]][{}[]]]>[([(){}]((){})){<<> -[(<[<<<{([(<{(<>())}(({}[])<<><>>)>)]){{[<[[<><>]{{}<>}]>[[<()[]>((){})]]]}[<({<<>{}>{[]<>}}(({}())[<><>])) -<<(<<[<{(({[({{}<>})<({}<>)<()[]>>]})<[(<{[]}<{}{}>>)(<{{}()}[<>[]]>)](<<<[]><(){}>>>{{{<>[]}([ -([[{[{<{{(([<([]{})[[]{}]>][<({}())[{}()]>{<[]{}><{}[]>}]))<([(({}<>))])>}}>}<<[<{[<<({}[]]([]{})>>]}><{ -<({[<({(({{[(<[]()>{{}{}})][<[{}{}]{()<>}>[<()()>]]}}){((<<{[]<>}>(({}<>){[]<>}>>(<[<>[]]{<>}><{[][]}[<><>]> -[(<({([{{{{{([(){}][<><>]){[(){}]{{}<>}}}((<{}{}>(()[]))[<{}()><[]()>])}{<({{}()}<<>{}])[{{}{}}{[]<>} -({<<{{{{(((<({<>()})({{}}{{}{}})>{{([]{})<<>{}>}{<[]{}>{()[]}}}){[<[<>[]}[[][]]>{[{}[]]<<>()>}]<{({}<>)<{} -[({{<<[{<({[<<{}{}>([][])><{(){}}>]{[[[]<>]][(<>()){{}}]}})(<[<{{}()}<<>[]>>([{}]{()<>})]>)>}[(<[({[<>[]]([] -({[([(<([[<(({[]{}}{[]{}})<{()()}{<>()>>)[<{{}<>}>({[][]}(<>[]))]>]{(<{{[]{}}[[][]]}[[()[]][ -{([<{<{([<[[[[{}()]]]{<{[]()}((){})><[[]]<<>>>}][<<<{}<>>{()<>}>{<{}()>[{}[]]}>[(([]<>))[<[]{}>[[]]]]]>]<[ -<{[{{([[(<<<{({}{})(()<>)}[<{}()><{}<>>]>>>(<{{[{}()][(){}]}([[]()]([]<>))}{{<{}[]>{{}[]}}{[[]{}]{() -{<{[<([{([[{{(<>[])[<>[]]}}][(<{[]()}<{}{}>>{<<>()>((){})])[{[<><>](()<>)}<<{}{}><<>[]>>]]])}]) -<[[[{<[<([[({[<>[]][()<>]}(({}[]){[]<>}))]])[([<<([])><<()[]>{<>[]}>><([()()]<[]()>){<<>[]><[]<>>}>]({<({}[] -((<{{{[(({[[([()[]]([][]))(<[]<>>([]()))](((()())([]<>)){(()[])([]<>)})][{<([]{})<[][]>>{<[]{}>{(){}} -(({{<[[{((((<<{}()>[()<>]>){[(()<>)([]())]})<{[<{}()>[[]()]]}<((<>())({}{}))[({}{}){{}<>}]>>))<[(({< -[<{[{{({<[{[(<[]{}>{(){}})({{}<>}{{}{}})]<([[][]][[][]])((<><>)<<>()))>}<({{{}()}{{}{}}}(<[]{}>{() -{{{{[{[{{<[[[{()<>}(<>[])]<{{}[]}[[][]]>]<<<<>>>>]{[[{()<>}<[]{}>]{{{}{})[{}[]]}]<(([]<>){{}()})>}>}[<([[({} -([<<(({(<{{{<{()<>}>}}{(<({}<>){[]{}}>[<<><>><()()>])}}(<(({<>()}<(){}>){(<>{})[<>()]})>[(({<>[]} -<{([[<{(((<(<[{}{}][(){}]>{<{}<>><[]<>>})<((<>())<()[]>)(<{}()>[[]<>])>>[(<[[]{}][[]()]>[<()()>[{}<>]] -<[{{(<{[<(<[{[[][]]<()<>>)<(()<>)[<>()]>][<{{}{}}(<>[])>(<()[]>(()()))]>)<{<[{[]{}}]>[{<[]<>><<>{}>}]}[<{< -[{((({({[<[<[(<>()){()[]}]([<>{}]{<>{}})>{[[[]<>][[][]]]{(()())[<>[]]}}]{{{{<>[]}{{}()}][([] -<[{[<{(<((<{<{[]{}}(()<>)><(()<>){(){}}>}[{[{}[]]}<(()())[()()]>]>{{[<()[]>]{(<>[])<()()>} -{<([<([{{{(({{()[]}}[([][]){(){}}]))}[[{{(<><>)<<>>}<<()()>>}][{[[[]<>]{(){}}]}<{{[]<>}<{}[]>}{{<>[]}< -<<[<{{[<[<<([[{}<>]{[][]}][[{}{}](()<>)])[([{}]({}{}))[([]<>)<<>[]>]])<[<[()<>]>{[[]{}]<{}{ -[{[{<[({<((<[<<><>>(()<>)](<{}[]><<>()>)>[{([]())[()<>]}])([<([][])<()<>>>([<><>])]))[[{({<>[]}[()[]])}[[{(){ -{[([[<{[<{<{[(<>[])<{}()>](((){})([]<>))}[({<>[]}[()[]])([[]<>][{}{}])]><{{<()()>[()]}(<[]<>>[{}<>]) -{[<([(({([<[([()[]]<[]{}>){<{}<>>(()<>>}]([(()<>)([]())]((<><>)({}())))>]){[{(<[[]{}][(){}]>({[]{} -[({<[{[<({<((<<><>>){[{}()]})<<{{}{}}[[]()]>(({}()))>>{[[{{}<>}({}<>)][(()<>)({}{})]]<{[()<> -[([<{<{<{[(<[((){})[<>[]]]{{{}<>}[{}[]]}><[[()()][()()]]>)([[{[][]}{[]()}]]({<[]<>>(()<>)}[[[]<>]({}<>)])) -<([<{[<<[<(<{{(){}}({}{})}[<<>()>(<>())]>[<<[][]>([]())>{[<><>]<{}()>}])>]{{[{[<{}{}>(<>{})][[<>()]<<>[] -<{([<<(<{{[{<[(){}]{[]}>((<>[]){()[]})}(<{<>}(()())>(<<>[]><<><>>))]<[<<[][]>([])>]>}}{[<<(<[]>{<>[]])(<()<>> -(<{([<{[(<<(<[(){}]({}())><{()[]}<[]()>>){[<<><>>[{}[]]]<({}<>)[[]<>]>}>{[[([]{})<{}[]>]][{<[] -<<({[<({<{[((({}))<(<>[])>)<[[<><>]([]())]>]}<{[<{(){}}(()())><<[]<>>{()[]}>]}>>[<{{{<()()>[[]()]}(< -[{[{<{[[{{{[<[(){}]{<><>}>(({}[]))]}<(<[[]<>]{<><>}>{(()){(){}}}>[({()()}<{}[]>)]>}}]{<((<{<(){}><{}<>>} -{([((<<([{<[[([][])<{}[]>][[(){}]{[]<>}]](<{[]{}}<<><>>>)>[{{{<>{}}([]{})}[<[]()>(()())]}{<(< -<{{((<{{({{<(<(){}>({}<>))[[{}[]]{[]{}}]>{[{(){}}{()[]}]({<>[]}<[][]>)}}([(<(){}>[[]<>])[[{}{}]<{}<>>] -[<[<({[<{{{{{<<>[]>}({<>()})}}([[(()<>)<()()>]]>}([(((<>{}))[[<>[]][()[]]])<{([]{})(()[])}>]<{ -<<[<{<{({<([({{}[]}){{{}()}{{}{}}}]<[{()()}<<><>>]{(<>())(()())}>)(<{({}<>)([]{})}(<<>{}><[]()>)>{ -([{({{<<<{{{((()[])(<>[])){(()[])[()<>]}}(((<>{})<()()>))}<<[{<>{}}{{}[]}]<(<><>){<>[]}>>(<{<>[]}<(){}>>)> -{[[(<({{[<<([<()[]>[(){}])<<[][]>[<><>]>)({({}())([]{})}[{{}()}({})])><<{{[][]}[()[]]}{{{}()}{<>[]}} -<(<[{<<{[{<({{()<>}[{}[]]}[<{}>({}<>)])<[{(){}}(<><>))>>[<{<[]{}>[{}()]}<[()]<<><>>>><{<{}{}>[[]<>]}[<()[]>( -<([{{{([<(<(<[()()]{[]()}>{[()()]{{}{}}}){[[[]<>]{[]{}}]<<()<>>>}>)[[{(({}<>)<<><>>)[[()()]{[]()}]}(<[(){}]{< -{[<{{<(<{<<[<(<>())({}())>[[()]{[]()}]]({{[]()}}<<[][]>{<>{}}>)>>(([[[{}[]]((){})]([[]{}]{ -<<<<(<{{<((<[<()()>{<>[]}]>)[[<({}())<(){}>>]{(<(){}><<>()>)[{<>[]}[{}<>]]}])(([<<<>{}>>[{[][]}{{}{}}]]{<[ -([[<<<({[[(<([<><>]{<>()})>(([<>][{}<>])<[[][]>([]{})>))({{<[]>{<>()}}{<[][]>[[]{}]}}<[{[]{}}{{}{}} -{[[<<(<<([(([{<>()}<<>()>]{[{}[]]{()[]}}){[[(){}){(){}}]{<<>[]>{[]<>}}})[<([[]]<<>{}>)>{{{<>{}}<<><>>}[[ -(<{{<([[[([[(<()()>[[]<>]){[{}]{[][]}>]])[<[{(<>)(()[])}({<>[]}[{}()])]{<[<>{}]{{}()}>{{()}{<>{}}}}>([ -{<[{(((([<[{{<<>()>[()()]}<([]())<[]()>>}<((<>))[<[]{}>{[]<>}]>){{([()]<<>[]>)[<[][]>{()}]}[{((){}) -((<{<{<(((<(({(){}}([][])){((){})<[]>})({(()[])(()())}{{()<>}[<>{}]})>[(<[()]<[]{}>>(([][]){<><> -{{{({[{(<<<<[[(){}]<<><>>]([[]{}]<{}[]>)>>>>[{{<[{<><>})[(<>[])[{}{}]]>{{<<><>>}({<><>}{()()}) -{{[{[(({[(({<[{}{}]>[{[]<>}[{}()]]}(((()<>)<()[]>))){{{<{}[]>{{}<>}}{{{}<>}}}<<<{}{}>>(({}()))>})({<<{ -{<{<[<(<{<[(<({}{})[[]{}]>{([]<>)[<>[]]})>([<{<>()}{[][]}><{()[]}<[][]>>][<{{}{}}{[]()}>[<<><>>[{}<>]]] -{({{[<(<[[<[[({}{}){<><>}]](({()<>}{{}<>}){({}<>)<()[]>})>]}><<<{{(({}{})<()()>)([{}[]][<>[]])} -(<<{<<{{[{((({[]{}}))<([<>()]{{}{}})(<{}{}><[]<>>)>)[{({{}{}}<()>)}([<{}[]>([]())]{<<>[]}([]{})})]}< -{{<{([[<[(<[[<{}<>>]({[][]}<<>{}>)][[[()<>][<>[]]]{[[][]]}]>(({([])[<><>]}[(()<>)<(){}>])<<[{}]{< -<{{{[<{[<<[<{[<><>]{[]{}}}[<{}()>{{}[]}]><<<[][]>{{}()}><(<>())[<>[]]>>]<[[<()[]>[<>[]]](({}<>))]>>]]}>]{([<( -[<{({{[{<<{<<[()<>]<<>()>>([<>[]]([]()))><[<<>{}>{{}{}}]>}(<{[()()][()()]}(([]{}))>)>([(({{}()}<[]{} -(<{{({({({<<((()<>)(()()))[(<>[]){<>[]}]>({({}[])[<>{}]})>})}){[[({{(<()<>>{<><>})<{<>[]}<{ -[[<<<{<<[<[[{<{}{}>(<>{})}]{([[][]][[]{}])<([]<>)<[]{}>>]]>[[<[[()[]]({}())](([]())[()<>])> -{[(<[[{({<{<[{(){}}]{[[][]]<()[]>}>}}[([<[{}[]]([][])><<[]()>[()()]>]({<()<>>(<>[])}<<(){}><<><>>>) -[{(<<{{[<{{{[[(){}]({}())]<(<>[])>}<{{()<>}(<><>)}>}}[(((([]())[(){}])(({}<>)<()()>))[<(<><>)<[]{}>> -<<<{<([[[({{<([]{})[{}()]>[([]<>)[[]()]]}(<<<><>>>)}[[{<()[]>({}<>)>]([[<><>]][(())[[]()]] -([{{([<<<{{(<[{}[]][{}()]><[<>()]{[]()}>)({{[]<>}[{}()]>({()<>}<{}()>))}[<<<{}<>>{[]()}>>]}>>> -{[<{{<{{<[[<({()[]}{<>{}}){{<>[]}{(){}}}>]]<([[[[]{}]{{}{}}][<{}()><[]{})]])({((<><>)[()[]])<[[]]<{}<>>>}[ -[[{(<<{<{<{<((<><>)[<><>])>}>({<(<[]()>[(){}>)>{{[[][]]}{{()()}{()()}}}})}{[{{((()())((){}))(({} -[{[<{[((<<[(<<<>[]>({}[])>(<<>>{<>[]})){{({}())[{}<>]}{{<><>}{<><>}}}][[{({}<>)}({<>()}[(){}])] -<<([[{([{{<<<<{}()>({}())>([()()])>(<([][])><<()[]>>)>}}{<{[<[<>{}][<><>]>]<[(()())[()<>]]<{{}{}}{[]< -{{[<{{[{{{<{<<<>[]><()<>>>(<{}<>><{}{}>)}<[((){})[[]{}]]{<{}>}>>}<[[([{}[]]{[]<>})][([()<>]<{} -[(([(((<{[{{<[[][]](<>{})><{{}[]}[(){}]>}{(({}[])([][]))<[{}[]][[]]>}}([[{[]}(()[])][([]<>){() -{[<{<<[<{([<({[]<>}[()]){[[]()]([]())}>{([<>]{<>{}})}])<(([({}[]){[]<>}]{([]<>)[[]<>]}){{<(){}}[{}[]]}([[]{ -[{<<<[<[{(<{({{}{}}[[]()])([[]()])}>)[[(({<>}({}())){{<>[]}<[]<>>})[(<<>{}>)]]]}{<[[[[{}()}(<>())]{<<><> -((([{[<({([[((<><>)[{}()])(({}<>)({}()))]{[<<>{}><<>()>]({()()}[<>])}]<[{[{}()]}([{}{}]<()()>)]>)}<([<[{[] -(<[<{[<[{[[<[<{}()>[[]]]>{{<<>>({}[])}<{{}<>}>}][({<()()>[()[]]>({[]()}))]]}]({<({<[{}()]{{}()}>{[()< -(<<([{<[<(<[[{[][]}[(){}]]]}<{{<{}{}>}{(()[])(()())}}>)>][[{[([([][])(<>())](<()>[[]()]))(<{[]()}{() -[{{<<<<{(({{({{}[]}<()[]>)({{}()}{<>()})}<[(<>())]{(<><>)}>}((([<>()]{{}[]})[<<>[]>(()[])])[(<{ -<[[{<([[<[{(({<>[]}({}()))(<[]<>>{<><>}))<[(<>[])(()<>)]{{(){}}{{}<>}}>}([[{()()}(()())]]((<[][]>([]()))(< -(<(<[{<([[({<<(){}>[{}()]>[<[]>[()()]]}(<<{}{}><[]<>>>({{}[]})))<[({[]()}[{}<>])<(()<>){[][]}>]{([ -{(<(((<[<<<[[(()())[{}]]({<>()}({}()))]<<{()()}(()())>[{<>[]}[[]<>]]>>>([{(<{}{}>{{}})<[{}[]](<><>)>)[<[<> -<[<([<{<<<{{{<()[]>{<>[]}}[<[][]>[{}()]]}}<{{{[]<>}<[]{}>}<{{}()}[()()]>}>>)>[([<{((<>{})[()( -<<[<<{([[[[<[([][])((){})][{{}()}({})]>([{{}{}}(<>[])])]{{(<<>[]>{()[]}){[<>()]{[][]}}}[{{<>}<{}<>>}<<{}()>(( -{{(<{[<<[{[(<<[]>(<><>)>[{[]()}{<>{}}))<{({}[])<[]{}>}{(<>{})[[][]]}>]<(([<>{}]([][]))<[[][]][<> -(({([{({<[<<{([]())(<>())}([<>{}])><({<>})<<<><>>>>>[<{[{}<>]{[][]}}<{()()}<[]{}>>>[{<()<>>{{}}} -<{[{({[(({[((<()>{()<>}))<([()[]]<<>()>)[{(){}}([])]>](({<()[]><{}<>>}({{}}([][]))))}))<<[[[[{( -[{<([[({{{{({([][])[<>{}]})[{({}{}){<>{}}}]}({[{[]{}}([])]({()()}<[]{}>)}<[[{}{}][{}[]]]{<(){}>{<>< -(<[{{{{[{(((<[[]())([]())>{<()()><[][]>})){<(<<>{}>[[]()]){{<>{}}[<><>]}>[<{<>()}<{}{}>>{<()[] -({{[{[[[{<{([<{}<>>[{}()]])(({()[]}{()[]}){<{}<>>{()}})}<<{[<><>]}<[()[]>{{}<>}>><((()[]))>>> -{<[(<{[(([({<[<>[]]<<><>>}[[<>()]{{}<>}]}[{<{}>}<[()<>]<[]()>>])(<[[<>()]{{}()}]<({}[])[{}()]>>([[<>{}]<< -{<[<{{(([{[[{<[][]>[<>[]]}<[{}<>]<<>{}>>]]{<(([]<>))((<>{})[<>{}])>{(<{}<>>[<>])([(){}]{<><>})}}}[{[({{}<> -<<({[(<{<[{{[<{}[]>]<[<>{}]{[]<>}>}}<([{[]<>}]{(<>{})}){(<[]<>><()>)[<()()>([]{})]}>](([{{[][]}[{}[]]}[{<>[ -[<[[[[<({([[[[<>()]{{}()}][{<>{}}{[]}]]<{<{}>{<>)}>]{[<[<><>]{()()}><((){})(()())>]{(({}[])){[()()]( -{<[[[<<<<<{[<[<><>]<()<>>>{{()[]}[{}()]}]<<[<><>]{()()}>>}({{{<>()}([]<>)}[[(){}][()[]]]})>>>>>] -(<[{{[[{({[{<{<>[]}[<>[]]>}]})}{{({{{([][])((){})}(({}[]))}([{<><>}(()[])]({<>{}}<{}>))}{([(( -<[[(<{({<<{{[{<><>}]<(<>{})<<>()>>}[<([]<>)(<>[])>[<{}<>><[]<>>]]}<({{{}<>}[()<>]}{[<>[]][[] -{{<[[<<<{{{(<[{}()]>[<(){}}(()[])])[[{(){}}<{}()>][({}[])([]{})]]}}[<<<[()()]{[][]}><<[]>>>{<<{}[]>{<>[]}>[< -((<<{([[([[<([[]{}]<[]{}>)>]](<({{{}{}}([][])}{(<>())[<><>]})[((()())[{}{}])[(<>{})[[]<>]]]>))[{{({{{}{}}[< -<<<(<(<[[<(<[{()[]}<{}{}>]>([{[]()}[()[]]]<(<>())>))[{({<>{}><{}<>>)}{[[{}()](())]<<()[]><<><>>>}]>{{<( -{{{<(({{[(({{<[]()><<>>}{[()[]]{<>{}}}})({<<()]<[]{}>>}([[()()]{[]<>}]))){<(<(<>()){[]<>}>[ -[({([{<(<[<{[<<>[]>[[]]]{[{}[]]<(){}>}}{<<[]()>({}())>([[]{}][[]()])]>]<<{{[{}{}][[]{}]}{{(){} -<{{<[[([[(<{{{<>[]}[()<>]}(<[]{}>)}<{[{}{}]({}{})}>><{[{{}[]}(<>{})]<{<><>}<{}{}>>}>)][<{({[(){})<()()>}) -<<{{[{{[[{{[({{}[]}[()[]])({[]<>}{{}()})](<<<>[]>{[]<>}>{{()[]}[<>()]})}}](<{{{<<><>><{}[]>}}}({ -[<[<<(<[((((<(<>[]}<[]>><{[][]}({}{})>))[<{[[][]]}([{}<>][{}])>[<{[]()}({}{})>{(()()){{}{} -[<<{[([[([{<[{(){}}[{}{}]]><{[[]<>][(){}]}<{[]{}}[()()]>>}({((<>))<{()}<[]{}>>}{[[[]]{<><>}]<[[]<>] -[[[{<([{[<[<{[<>()]<()<>>}<{<>()}<[]<>>>>([(<>{})(<>[])]<<(){}><[]<>>>)]({{[<>{}]}({<>[]}<()[]>)}[(<{}< -{<<[[{([{((({[{}()]{()[]}}[<{}>[{}{}]]))({[<(){}><()[]>]}))}])[<(<([([<>{}))<[[][]]{(){}}>])( -[{(<<{<[[{<[{[{}[]](()<>)}[[{}{}][[]<>]]]><(<(<>[])({}())>[{{}{}}<<>()>>)>}<{(<<{}[]>[[]()]>{< -<{(((([<{[{[<<(){}>[()<>]>{<{}>({}())}]{[{<>()]({}{})]}}][(<<{()()}>({[][]}<{}[]>)>)]}[(<[{( -([<((<<[([[[<[()()]<{}()>>]<(<()()>[[]])[<{}<>>((){})]>}{({((){}){[]{}}}[[[]]<{}<>>])(<{()[]}[()[ -{((<[({<<({(<{<>[]}{[][]}>){<<()()>{[][]}><{[]{}}>}}<<[<[]>(<>())]<<<>{}>{{}()}>>[[[<>{}]<()()}]< -[[<{{{({([((<[()<>]<{}>><(()[])[{}()]>)[({<><>}({}))<<{}<>><[]{}>>]){[([{}<>](()()))]<[{() -{<<[[{[[[[[[[[<>()][{}]]<(<>())(()[])>]]<{[<[]<>>({}{})]}<[({}())][{{}()}{{}[]}]>>]<[[(<()()>{[]{}}) diff --git a/2021/day-10.ts b/2021/day-10.ts deleted file mode 100644 index da5cf5b..0000000 --- a/2021/day-10.ts +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -const SYNTAX_ERROR_SCORE: Record = { - ')': 3, - ']': 57, - '}': 1197, - '>': 25137, -}; - -const AUTOCOMPLETE_SCORE: Record = { - ')': 1, - ']': 2, - '}': 3, - '>': 4, -}; - -const PAIR_MAPPING: Record = { - '(': ')', - '[': ']', - '{': '}', - '<': '>', -}; - -function scoreAutoComplete(symbolStack: string[]) { - let result = 0; - let symbol; - while ((symbol = symbolStack.pop())) { - result *= 5; - result += AUTOCOMPLETE_SCORE[symbol]; - } - return result; -} - -/** - * Check the line for syntax errors - * - * Returns the score of the syntax error, or `0` if the line is syntactically - * fine, or the negative score of the autocompletion when the line is incomplete. - * - * @param line - */ -function syntaxCheck(line: string): number { - /** Stack of "open" things that need closing */ - const expectedNextClosing: string[] = []; - for (let i = 0; i < line.length; i++) { - const c = line[i]; - // If c is a closing symbol, then it must match to the one on the top of - // the stack, otherwise the line is corrupt. - const closingSymbol = PAIR_MAPPING[c]; - if (closingSymbol) { - // c is opening - expectedNextClosing.push(closingSymbol); - } else { - // c is already closing - const expected = expectedNextClosing.pop(); - if (c === expected) { - // Good, proceed. - } else { - // Not good, return an error. - return SYNTAX_ERROR_SCORE[c]; - } - } - } - - if (expectedNextClosing.length === 0) { - // All good, nothing open! - return 0; - } else { - // Something is still open, so the line is incomplete. - return -scoreAutoComplete(expectedNextClosing); - } -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - let syntaxErrorScore = 0; - let autoCompleteScores: number[] = []; - - return new Promise((resolve, reject) => { - rl.on('line', (line) => { - // Process `line` here - const s = syntaxCheck(line); - if (s === 0) { - // Complete, we don't care. - return; - } - if (s < 0) { - // Incomplete - autoCompleteScores.push(-s); - } else { - // Error - syntaxErrorScore += s; - } - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - autoCompleteScores.sort((a, b) => a - b); - console.log( - `Results for ${input}: syntax error score ${syntaxErrorScore}, auto complete score ${ - autoCompleteScores[ - Math.floor(autoCompleteScores.length / 2) - ] - }` - ); - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - '-example', - '', -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-11-example-mini.input b/2021/day-11-example-mini.input deleted file mode 100644 index ae21dd2..0000000 --- a/2021/day-11-example-mini.input +++ /dev/null @@ -1,5 +0,0 @@ -11111 -19991 -19191 -19991 -11111 diff --git a/2021/day-11-example.input b/2021/day-11-example.input deleted file mode 100644 index 03743f6..0000000 --- a/2021/day-11-example.input +++ /dev/null @@ -1,10 +0,0 @@ -5483143223 -2745854711 -5264556173 -6141336146 -6357385478 -4167524645 -2176841721 -6882881134 -4846848554 -5283751526 diff --git a/2021/day-11-example.output b/2021/day-11-example.output deleted file mode 100644 index 009e068..0000000 --- a/2021/day-11-example.output +++ /dev/null @@ -1,239 +0,0 @@ -Before any steps: -5483143223 -2745854711 -5264556173 -6141336146 -6357385478 -4167524645 -2176841721 -6882881134 -4846848554 -5283751526 - -After step 1: -6594254334 -3856965822 -6375667284 -7252447257 -7468496589 -5278635756 -3287952832 -7993992245 -5957959665 -6394862637 - -After step 2: -8807476555 -5089087054 -8597889608 -8485769600 -8700908800 -6600088989 -6800005943 -0000007456 -9000000876 -8700006848 - -After step 3: -0050900866 -8500800575 -9900000039 -9700000041 -9935080063 -7712300000 -7911250009 -2211130000 -0421125000 -0021119000 - -After step 4: -2263031977 -0923031697 -0032221150 -0041111163 -0076191174 -0053411122 -0042361120 -5532241122 -1532247211 -1132230211 - -After step 5: -4484144000 -2044144000 -2253333493 -1152333274 -1187303285 -1164633233 -1153472231 -6643352233 -2643358322 -2243341322 - -After step 6: -5595255111 -3155255222 -3364444605 -2263444496 -2298414396 -2275744344 -2264583342 -7754463344 -3754469433 -3354452433 - -After step 7: -6707366222 -4377366333 -4475555827 -3496655709 -3500625609 -3509955566 -3486694453 -8865585555 -4865580644 -4465574644 - -After step 8: -7818477333 -5488477444 -5697666949 -4608766830 -4734946730 -4740097688 -6900007564 -0000009666 -8000004755 -6800007755 - -After step 9: -9060000644 -7800000976 -6900000080 -5840000082 -5858000093 -6962400000 -8021250009 -2221130009 -9111128097 -7911119976 - -After step 10: -0481112976 -0031112009 -0041112504 -0081111406 -0099111306 -0093511233 -0442361130 -5532252350 -0532250600 -0032240000 - -After step 20: -3936556452 -5686556806 -4496555690 -4448655580 -4456865570 -5680086577 -7000009896 -0000000344 -6000000364 -4600009543 - -After step 30: -0643334118 -4253334611 -3374333458 -2225333337 -2229333338 -2276733333 -2754574565 -5544458511 -9444447111 -7944446119 - -After step 40: -6211111981 -0421111119 -0042111115 -0003111115 -0003111116 -0065611111 -0532351111 -3322234597 -2222222976 -2222222762 - -After step 50: -9655556447 -4865556805 -4486555690 -4458655580 -4574865570 -5700086566 -6000009887 -8000000533 -6800000633 -5680000538 - -After step 60: -2533334200 -2743334640 -2264333458 -2225333337 -2225333338 -2287833333 -3854573455 -1854458611 -1175447111 -1115446111 - -After step 70: -8211111164 -0421111166 -0042111114 -0004211115 -0000211116 -0065611111 -0532351111 -7322235117 -5722223475 -4572222754 - -After step 80: -1755555697 -5965555609 -4486555680 -4458655580 -4570865570 -5700086566 -7000008666 -0000000990 -0000000800 -0000000000 - -After step 90: -7433333522 -2643333522 -2264333458 -2226433337 -2222433338 -2287833333 -2854573333 -4854458333 -3387779333 -3333333333 - -After step 100: -0397666866 -0749766918 -0053976933 -0004297822 -0004229892 -0053222877 -0532222966 -9322228966 -7922286866 -6789998766 diff --git a/2021/day-11.input b/2021/day-11.input deleted file mode 100644 index b358065..0000000 --- a/2021/day-11.input +++ /dev/null @@ -1,10 +0,0 @@ -8271653836 -7567626775 -2315713316 -6542655315 -2453637333 -1247264328 -2325146614 -2115843171 -6182376282 -2384738675 diff --git a/2021/day-11.ts b/2021/day-11.ts deleted file mode 100644 index 5dbb9bb..0000000 --- a/2021/day-11.ts +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -function printField(field: number[][]) { - field.forEach((row) => console.log(row.join(''))); - console.log(); -} - -function simulateStep(field: number[][]): number[][] { - const newField: number[][] = []; - /** To-Do list of [row, col] octopi that must still flash in this step */ - const mustFlash: [number, number][] = []; - for (let j = 0; j < field.length; j++) { - const row = field[j]; - const newRow = new Array(row.length); - for (let i = 0; i < row.length; i++) { - newRow[i] = row[i] + 1; - if (newRow[i] > 9) { - mustFlash.push([j, i]); - } - } - newField.push(newRow); - } - - // Process flashes until there are none left - // Order doesn't really matter, so we just use a stack. - let nextFlash: [number, number] | undefined; - while ((nextFlash = mustFlash.pop())) { - // Bump all neighbors of this octopus in their energy level - // and put any of them that reached 10 onto the todo list - for ( - let nj = Math.max(nextFlash[0] - 1, 0); - nj <= Math.min(nextFlash[0] + 1, newField.length - 1); - nj++ - ) { - const row = newField[nj]; - for ( - let ni = Math.max(nextFlash[1] - 1, 0); - ni <= Math.min(nextFlash[1] + 1, row.length - 1); - ni++ - ) { - if (nj == nextFlash[0] && ni === nextFlash[1]) { - continue; - } - - if (++row[ni] === 10) { - mustFlash.push([nj, ni]); - } - } - } - } - - // Reset the energy of all octopi > 9 to back to 0. - // The number of these resets represents the number of flashes - // that have happened (which we let the caller calculate). - for (let j = 0; j < newField.length; j++) { - const row = newField[j]; - for (let i = 0; i < row.length; i++) { - if (row[i] > 9) { - row[i] = 0; - } - } - } - return newField; -} - -function simulate(field: number[][], steps: number = 100): number { - console.log(`Before any steps:`); - printField(field); - let workField = field; - let flashes = 0; - for (let step = 1; step <= steps; step++) { - workField = simulateStep(workField); - - // A octopus with energy 0 has just flashed, so count those. - const newFlashes = workField.reduce( - (result, row) => - result + - row.reduce( - (rowCount, e) => (e === 0 ? rowCount + 1 : rowCount), - 0 - ), - 0 - ); - if (newFlashes === workField.length * workField[0].length) { - console.log(`Step ${step}: Everyone flashed!`); - printField(workField); - break; - } - flashes += newFlashes; - - if (step < 10 || step % 10 === 0) { - console.log(`After step ${step}:`); - printField(workField); - //console.log(`... ${flashes} flashes seen`); - } - } - - return flashes; -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - return new Promise((resolve, reject) => { - const field: number[][] = []; - - rl.on('line', (line) => { - field.push(Array.from(line.trim()).map((c) => parseInt(c, 10))); - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - const flashes = simulate(field, 100); - console.log(`Results for ${input}: ${flashes} flashes`); - simulate(field, 5000); - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - //'-example-mini', - //'-example', - '', -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-12-example-1.input b/2021/day-12-example-1.input deleted file mode 100644 index 6fd8c41..0000000 --- a/2021/day-12-example-1.input +++ /dev/null @@ -1,7 +0,0 @@ -start-A -start-b -A-c -A-b -b-d -A-end -b-end diff --git a/2021/day-12-example-2.input b/2021/day-12-example-2.input deleted file mode 100644 index 62cc714..0000000 --- a/2021/day-12-example-2.input +++ /dev/null @@ -1,10 +0,0 @@ -dc-end -HN-start -start-kj -dc-start -dc-HN -LN-dc -HN-end -kj-sa -kj-HN -kj-dc diff --git a/2021/day-12-example-3.input b/2021/day-12-example-3.input deleted file mode 100644 index 65f3833..0000000 --- a/2021/day-12-example-3.input +++ /dev/null @@ -1,18 +0,0 @@ -fs-end -he-DX -fs-he -start-DX -pj-DX -end-zg -zg-sl -zg-pj -pj-he -RW-he -fs-DX -pj-RW -zg-RW -start-pj -he-WI -zg-he -pj-fs -start-RW diff --git a/2021/day-12.input b/2021/day-12.input deleted file mode 100644 index f16181c..0000000 --- a/2021/day-12.input +++ /dev/null @@ -1,23 +0,0 @@ -xz-end -CJ-pt -pt-QW -hn-SP -pw-CJ -SP-end -hn-pt -GK-nj -fe-nj -CJ-nj -hn-ZZ -hn-start -hn-fe -ZZ-fe -SP-nj -SP-xz -ZZ-pt -nj-ZZ -start-ZZ -hn-GK -CJ-end -start-fe -CJ-xz diff --git a/2021/day-12.ts b/2021/day-12.ts deleted file mode 100644 index bed7b44..0000000 --- a/2021/day-12.ts +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -const START = 'start'; -const END = 'end'; - -type DiGraph = Record; -type Path = string; - -function canGoIntoPart1(visitedCaves: string[], cave: string): boolean { - return cave.toLowerCase() === cave ? !visitedCaves.includes(cave) : true; -} - -function canGoIntoPart2(visitedCaves: string[], cave: string): boolean { - if (cave === START) { - // No need to check, we came from there - return false; - } else if (cave === END) { - // Fine to go into, and we know the caller won't ask again - return true; - } else if (cave.toUpperCase() === cave) { - return true; - } - - // small cave, check whether the invariant requested still holds: At most - // one small cave visited twice. - const counters: Record = { [cave]: 1 }; - let seenDoubleVisit = false; - for (const visitedCave of visitedCaves) { - if (visitedCave.toUpperCase() === visitedCave) { - continue; - } - const newCount = (counters[visitedCave] ?? 0) + 1; - counters[visitedCave] = newCount; - - // Can be 3 if we have a double visit for the requested cave already - if (newCount >= 2) { - if (seenDoubleVisit) { - return false; - } - seenDoubleVisit = true; - } - } - return true; -} - -function countPaths( - graph: DiGraph, - openPaths: Set, - canGoInto = canGoIntoPart1 -): number { - let result = 0; - let closedPaths: Set = new Set(); - - // While there are open paths: Assume the first one is active, and - // expand it for all possible targets from its last node. If we reach - // END: consider that one closed, increase the count, and pick the next one to continue - // with. - // Considerations: - // - we need to avoid creating multiple same open paths - // - we need to avoid creating a new open path that matches a previously closed one - // - presumably a loop A-B doesn't exist, as we cannot exhaustively count the paths - // (IOW: it would be infinitely many, but we must not try that!) - while (openPaths.size > 0) { - // A stack-ish interface would be nice, or just an iterator.remove() ... - const active = openPaths.values().next().value as string; - openPaths.delete(active); - - const visitedCaves = active.split(/-/); - const last = visitedCaves[visitedCaves.length - 1]; - for (let nextCave of graph[last]) { - if (!canGoInto(visitedCaves, nextCave)) { - continue; - } - const potential = `${active}-${nextCave}`; - if (closedPaths.has(potential) || openPaths.has(potential)) { - continue; - } - if (nextCave === END) { - closedPaths.add(potential); - result++; - } else { - openPaths.add(potential); - } - } - } - return result; -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - const graph: DiGraph = {}; - - return new Promise((resolve, reject) => { - rl.on('line', (line) => { - const [from, to] = line.split(/-/); - - // Throw into our DiGraph structure - let targets = graph[from] ?? []; - targets.push(to); - graph[from] = targets; - targets = graph[to] ?? []; - targets.push(from); - graph[to] = targets; - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - const paths = countPaths(graph, new Set([START])); - const pathsP2 = countPaths(graph, new Set([START]), canGoIntoPart2); - console.log( - `Results for ${input}: ${paths} paths (${pathsP2} for variant 2)` - ); - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - '-example-1', - '-example-2', - '-example-3', - '', -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-13-example.input b/2021/day-13-example.input deleted file mode 100644 index 282114c..0000000 --- a/2021/day-13-example.input +++ /dev/null @@ -1,21 +0,0 @@ -6,10 -0,14 -9,10 -0,3 -10,4 -4,11 -6,0 -6,12 -4,1 -0,13 -10,12 -3,4 -3,0 -8,4 -1,10 -2,14 -8,10 -9,0 - -fold along y=7 -fold along x=5 diff --git a/2021/day-13.input b/2021/day-13.input deleted file mode 100644 index b2b2c61..0000000 --- a/2021/day-13.input +++ /dev/null @@ -1,934 +0,0 @@ -60,140 -1044,50 -878,203 -641,606 -669,606 -947,686 -370,534 -251,703 -1215,432 -1280,542 -1263,481 -701,703 -47,257 -1173,820 -1082,387 -1220,217 -152,796 -624,799 -522,147 -951,584 -1255,144 -1179,534 -224,296 -488,527 -99,838 -189,857 -440,766 -1148,302 -492,190 -82,530 -1019,514 -75,707 -1084,589 -710,429 -1123,666 -1192,810 -755,56 -791,866 -788,876 -363,42 -1290,429 -676,17 -208,362 -976,492 -1290,744 -237,705 -961,831 -137,596 -1218,312 -228,3 -795,4 -1275,798 -1098,93 -649,234 -266,844 -410,187 -291,852 -597,598 -212,801 -131,360 -1260,607 -1069,184 -438,198 -763,210 -1272,529 -55,592 -751,822 -383,358 -228,611 -746,217 -219,358 -713,282 -556,443 -957,78 -363,14 -1203,28 -542,409 -787,422 -788,147 -845,526 -109,826 -90,677 -1091,358 -90,217 -382,40 -764,518 -944,618 -835,819 -156,672 -653,289 -1253,737 -912,236 -75,365 -320,784 -284,729 -649,794 -167,341 -408,635 -835,75 -599,21 -92,358 -557,113 -62,417 -597,150 -1099,257 -610,586 -393,522 -1203,600 -875,403 -35,686 -1275,422 -1141,872 -184,362 -730,390 -726,809 -234,689 -87,259 -1223,22 -100,346 -992,236 -1064,584 -947,42 -182,178 -1215,74 -316,368 -95,462 -1203,236 -1034,261 -547,600 -181,320 -1212,611 -1171,628 -1150,284 -982,669 -1266,756 -694,305 -803,724 -445,551 -1173,688 -1173,686 -542,428 -537,750 -567,299 -676,196 -594,476 -539,413 -989,800 -773,103 -195,472 -887,24 -1014,411 -72,236 -1103,250 -195,422 -16,82 -395,696 -812,217 -392,731 -925,494 -980,79 -537,103 -219,403 -1154,670 -1250,306 -927,536 -832,131 -1228,513 -609,191 -937,78 -612,646 -264,809 -1190,197 -57,109 -701,191 -1082,3 -416,266 -940,534 -3,117 -1237,593 -437,686 -933,808 -408,859 -1039,536 -788,828 -681,126 -55,693 -1073,441 -795,101 -1131,170 -1256,854 -179,75 -330,815 -131,870 -64,443 -510,828 -1111,96 -895,807 -1016,857 -199,239 -1240,210 -710,465 -873,686 -765,675 -1253,785 -1163,147 -1014,595 -443,861 -1196,353 -719,121 -194,707 -306,660 -348,822 -624,859 -1190,151 -559,500 -1012,421 -756,548 -600,465 -53,798 -1212,731 -442,9 -30,156 -1231,502 -1171,345 -1102,362 -276,358 -786,373 -272,40 -448,295 -154,124 -1297,493 -306,698 -269,176 -1089,292 -791,28 -584,460 -1014,483 -179,724 -495,501 -947,852 -420,660 -1218,358 -75,463 -850,633 -663,254 -602,696 -887,276 -32,37 -358,231 -619,514 -115,481 -1071,87 -1215,522 -137,52 -547,206 -547,210 -579,871 -1203,654 -1126,851 -1266,138 -1183,696 -768,18 -997,717 -536,829 -373,302 -986,392 -199,605 -137,368 -373,592 -1156,124 -890,533 -803,500 -211,257 -648,850 -1004,38 -522,66 -269,381 -1072,714 -1250,588 -902,259 -803,595 -735,502 -1215,822 -333,94 -118,810 -1203,866 -711,715 -423,618 -656,858 -154,546 -577,617 -1310,858 -1223,747 -1150,232 -999,842 -30,409 -435,627 -818,750 -997,24 -241,262 -587,618 -75,879 -597,282 -925,16 -79,392 -644,93 -79,54 -360,37 -656,652 -1248,477 -48,312 -470,250 -848,366 -1146,876 -1054,877 -115,413 -455,15 -1092,373 -376,39 -982,225 -875,267 -492,893 -731,707 -162,704 -508,812 -641,292 -251,191 -328,669 -192,752 -808,212 -182,268 -485,882 -455,798 -231,170 -559,72 -855,798 -546,518 -179,453 -402,166 -979,789 -1158,796 -495,841 -42,565 -1019,42 -1116,822 -1074,434 -604,485 -599,715 -579,891 -475,371 -647,786 -1297,736 -398,809 -1064,785 -798,868 -1158,462 -716,844 -440,128 -1079,432 -616,305 -546,297 -160,610 -850,261 -417,441 -199,646 -221,292 -555,345 -803,394 -54,40 -55,302 -811,196 -810,348 -1098,765 -870,576 -1168,610 -1186,198 -557,186 -969,870 -1231,726 -1193,567 -1235,15 -962,682 -495,5 -483,868 -118,65 -1049,522 -13,288 -50,607 -1302,658 -1096,766 -147,441 -298,197 -152,656 -366,618 -907,324 -547,152 -850,185 -408,259 -98,3 -348,212 -711,179 -1192,829 -1218,582 -1125,63 -1255,302 -470,436 -187,676 -1039,201 -764,737 -480,436 -167,497 -793,746 -139,628 -723,46 -927,302 -773,343 -517,746 -264,85 -920,253 -237,413 -880,744 -1076,358 -600,37 -634,474 -132,847 -398,85 -147,453 -1245,113 -184,868 -1310,312 -944,365 -947,462 -529,233 -144,66 -169,458 -376,407 -659,565 -928,406 -928,488 -378,234 -167,273 -619,96 -127,463 -616,589 -875,491 -1016,373 -234,88 -288,141 -154,796 -492,592 -206,295 -189,37 -120,487 -851,192 -1158,210 -1136,458 -465,609 -64,451 -338,882 -426,3 -599,742 -1116,707 -326,225 -1310,36 -827,644 -877,740 -823,341 -701,367 -591,121 -107,206 -127,737 -1297,323 -1154,672 -226,137 -862,422 -1039,21 -199,248 -666,93 -788,187 -808,236 -980,815 -452,618 -634,420 -75,187 -540,353 -508,364 -1213,840 -13,401 -934,487 -442,801 -1144,647 -20,429 -830,10 -962,822 -527,96 -1064,635 -927,469 -1278,93 -763,476 -162,381 -884,387 -843,101 -666,98 -1163,441 -1253,598 -1111,289 -137,688 -507,724 -628,93 -893,441 -669,323 -937,592 -348,38 -1305,772 -382,37 -335,674 -781,233 -316,436 -763,152 -98,731 -1255,750 -1012,697 -112,474 -850,374 -194,72 -30,738 -60,306 -912,85 -152,210 -950,521 -408,707 -554,361 -1185,233 -50,633 -1084,305 -401,817 -485,22 -360,521 -1236,504 -753,759 -787,702 -577,169 -415,807 -1039,469 -1257,798 -313,870 -786,521 -67,724 -349,831 -830,458 -1176,473 -843,666 -917,522 -540,317 -554,346 -189,78 -589,217 -124,170 -873,667 -494,284 -60,418 -875,851 -691,870 -1299,89 -950,821 -524,521 -1228,364 -641,323 -1198,585 -915,500 -765,826 -65,217 -770,353 -1268,565 -30,95 -199,319 -969,269 -60,476 -649,772 -798,610 -845,609 -676,474 -1215,72 -900,707 -1031,481 -985,829 -1081,113 -559,432 -1041,612 -1168,436 -1091,627 -259,842 -644,25 -48,821 -276,234 -822,247 -170,222 -462,80 -60,364 -763,236 -475,523 -435,267 -663,786 -984,225 -49,86 -564,574 -512,610 -295,310 -470,644 -226,753 -981,381 -825,12 -868,885 -850,66 -114,200 -1034,660 -1034,536 -1084,757 -356,645 -134,697 -663,168 -1280,794 -154,616 -219,43 -669,602 -882,305 -912,877 -902,707 -80,147 -333,22 -475,724 -114,423 -179,441 -353,816 -373,78 -1126,362 -378,633 -1091,267 -127,605 -1004,698 -1115,422 -152,124 -152,238 -840,436 -37,596 -209,103 -574,859 -1038,406 -423,870 -329,829 -835,5 -947,880 -599,40 -546,597 -704,373 -107,654 -325,829 -1143,497 -1231,392 -783,463 -132,299 -199,289 -199,575 -604,760 -1196,200 -882,589 -599,179 -355,555 -803,170 -1190,487 -296,540 -622,373 -0,134 -494,732 -599,88 -1039,267 -580,504 -1118,142 -1076,458 -1225,122 -698,248 -171,26 -748,361 -1054,448 -1009,302 -1091,806 -868,801 -816,732 -816,367 -634,17 -873,227 -711,854 -1131,75 -488,303 -1173,526 -405,49 -565,33 -156,782 -401,705 -169,882 -977,648 -1215,462 -515,852 -716,50 -1310,582 -1146,18 -1220,798 -256,448 -1173,746 -328,225 -5,682 -810,546 -518,37 -825,22 -73,593 -928,40 -48,582 -1001,196 -1143,341 -1262,760 -1235,707 -1044,844 -835,276 -319,474 -1136,686 -893,840 -601,798 -1144,695 -256,85 -502,236 -1179,360 -319,226 -1230,411 -830,436 -909,705 -972,78 -875,627 -507,500 -490,876 -95,432 -430,296 -284,117 -741,772 -815,393 -1255,693 -713,765 -152,18 -771,413 -1163,394 -62,346 -783,157 -862,295 -127,289 -902,310 -950,73 -940,86 -751,598 -1014,354 -1166,66 -770,149 -1014,299 -160,284 -1307,777 -602,24 -437,667 -403,324 -237,481 -1019,380 -1039,592 -597,737 -383,21 -612,777 -994,353 -420,434 -1303,786 -475,819 -1096,16 -320,492 -1215,820 -1148,381 -1173,74 -50,756 -3,777 -649,212 -291,490 -273,292 -195,254 -55,806 -1227,726 -626,421 -75,529 -0,652 -502,682 -1029,367 -470,868 -1101,103 -835,371 -97,840 -686,95 -98,611 -1026,729 -517,368 -172,124 -545,219 -238,266 -572,866 -1278,37 -731,871 -1255,152 -35,422 -1101,343 -691,798 -1091,536 -763,742 -57,737 -738,866 -1084,753 -120,645 -1175,866 -783,96 -1243,618 -972,423 -6,558 -604,16 -887,618 -214,128 -1253,150 -1026,777 -234,458 -793,526 -1088,203 -117,327 -1218,88 -27,675 -994,126 -1054,533 -492,302 -1290,598 -562,689 -137,746 -1158,434 -1290,868 -1126,868 -62,253 -244,707 -88,833 -324,79 -1034,633 -1091,403 -335,726 -694,589 -420,436 -1129,320 -1268,613 -1111,319 -268,691 -108,821 -591,773 -547,294 -502,212 -530,276 -72,889 -1300,796 -808,434 -435,206 -1220,677 -326,673 -1201,675 -1086,296 -962,196 -1256,653 -16,812 -845,543 -11,89 -701,815 -166,695 -1222,490 -730,504 -319,420 -502,695 -174,10 -38,529 -1246,443 -644,210 -783,320 -798,162 -353,509 -793,368 -1150,214 -95,208 -984,381 -1300,93 -390,473 -594,844 -935,481 -494,527 -920,473 -1300,126 -303,176 -348,408 -284,777 -609,703 -929,292 -1198,757 -990,558 -1123,676 -607,376 -1230,35 -1029,302 -13,323 -1059,703 -669,571 -1190,743 -686,156 -498,728 -721,677 -1029,527 -986,502 -1294,812 -606,582 -1235,529 - -fold along x=655 -fold along y=447 -fold along x=327 -fold along y=223 -fold along x=163 -fold along y=111 -fold along x=81 -fold along y=55 -fold along x=40 -fold along y=27 -fold along y=13 -fold along y=6 diff --git a/2021/day-13.ts b/2021/day-13.ts deleted file mode 100644 index 48b7c4c..0000000 --- a/2021/day-13.ts +++ /dev/null @@ -1,165 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -type Dot = [row: number, col: number]; -interface Fold { - /** Coordinate at which to fold */ - coord: number; - /** Axis index into the dot structure: '0' means mirror the row, '1' means mirror the column */ - index: number; -} - -function printDots( - caption: string, - dots: Dot[], - { - maxRow, - maxCol, - foldRow = -1, - foldCol = -1, - }: { maxRow: number; maxCol: number; foldRow?: number; foldCol?: number } -) { - console.log(caption); - // Really inefficient logic :) - for (let row = 0; row < maxRow; row++) { - if (row === foldRow) { - console.log(''.padEnd(maxCol + 1, '-')); - continue; - } - - const cols = dots - .filter(([dotRow]) => row === dotRow) - .map(([, dotCol]) => dotCol) - .sort((a, b) => b - a); - let line = ''; - let col; - while (typeof (col = cols.pop()) !== 'undefined') { - line += '#'.padStart(col - line.length + 1, '.'); - } - - let paddedLine = line.padEnd(maxCol + 1, '.'); - if (foldCol !== -1) { - paddedLine = - paddedLine.slice(0, foldCol) + - '|' + - paddedLine.slice(foldCol + 1); - } - console.log(paddedLine); - } -} - -function applyFold( - dots: Dot[], - { index: axis, coord }: Fold, - { maxRow, maxCol }: { maxRow: number; maxCol: number } -): Dot[] { - // Folding is done by "mirroring" the coordinates along the axis, and removing - // any duplicate coordinate pairs. The duplicate detection is done by - // calculating a single coordinate-index from the row/col: index = row * (maxCol + 1) + col, - // and keeping those in a set. - const printOpts = { - maxRow, - maxCol, - foldCol: axis === 1 ? coord : -1, - foldRow: axis === 0 ? coord : -1, - }; - printDots(`before fold ${axis ? 'x' : 'y'} at ${coord}`, dots, printOpts); - const result: Dot[] = []; - const seenPairs = new Set(); - for (const dot of dots) { - let newDot: Dot; - if (dot[axis] < coord) { - // Retain - newDot = dot; - } else { - // Mirror on axis - newDot = [0, 0]; - - newDot[axis] = coord - (dot[axis] - coord); - const otherAxis = (axis + 1) % 2; - newDot[otherAxis] = dot[otherAxis]; - } - - const index = newDot[0] * (maxCol + 1) + newDot[1]; - if (!seenPairs.has(index)) { - seenPairs.add(index); - result.push(newDot); - } - } - printDots('after', result, printOpts); - return result; -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - const dots: Dot[] = []; - const folds: Fold[] = []; - let maxRow = 0; - let maxCol = 0; - - return new Promise((resolve, reject) => { - rl.on('line', (line) => { - if (!line) { - return; - } - - const [colS, rowS] = line.split(/,/); - if (rowS) { - const col = parseInt(colS, 10); - const row = parseInt(rowS, 10); - maxRow = Math.max(maxRow, row); - maxCol = Math.max(maxCol, col); - dots.push([row, col]); - } else { - const [instructionAndAxis, coord] = line.split(/=/); - folds.push({ - coord: parseInt(coord, 10), - index: instructionAndAxis === 'fold along x' ? 1 : 0, - }); - } - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - const afterFirstFold = applyFold(dots, folds[0], { - maxRow, - maxCol, - }); - console.log(`Results for ${input}: ${afterFirstFold.length} dots`); - - let workDots = afterFirstFold; - for (const fold of folds.slice(1)) { - workDots = applyFold(workDots, fold, { maxRow, maxCol }); - } - printDots('final', workDots, { maxRow, maxCol }); - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = ['-example', '']; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-14-example.input b/2021/day-14-example.input deleted file mode 100644 index b5594dd..0000000 --- a/2021/day-14-example.input +++ /dev/null @@ -1,18 +0,0 @@ -NNCB - -CH -> B -HH -> N -CB -> H -NH -> C -HB -> C -HC -> B -HN -> C -NN -> C -BH -> H -NC -> B -NB -> B -BN -> B -BB -> N -BC -> B -CC -> N -CN -> C diff --git a/2021/day-14.input b/2021/day-14.input deleted file mode 100644 index 591c6c8..0000000 --- a/2021/day-14.input +++ /dev/null @@ -1,102 +0,0 @@ -PBFNVFFPCPCPFPHKBONB - -KK -> S -FO -> B -PP -> O -HN -> S -CN -> H -VH -> P -BK -> B -VC -> N -CB -> H -OC -> K -BF -> P -FV -> K -SP -> F -OP -> K -SS -> B -NN -> O -CS -> K -CF -> K -FF -> S -SV -> P -OK -> S -CO -> F -OB -> K -BH -> B -HH -> S -VB -> V -KV -> H -CK -> V -NV -> N -SF -> V -PK -> H -PV -> N -FB -> O -BO -> K -FP -> N -OF -> N -FK -> O -VK -> V -NO -> V -NS -> C -KC -> S -VF -> V -BV -> N -CP -> K -PB -> V -CC -> S -NH -> B -CV -> P -SO -> V -NC -> O -HK -> K -SB -> H -OO -> V -HO -> P -PS -> B -BC -> P -KO -> C -KB -> C -VV -> F -BS -> F -HB -> B -KN -> S -FC -> C -SN -> S -HC -> O -HP -> F -BP -> V -ON -> K -BB -> K -KH -> O -NP -> H -KS -> N -SH -> K -VP -> O -PF -> O -HF -> S -BN -> S -NK -> C -FH -> O -CH -> B -KP -> B -FN -> K -OV -> P -VS -> K -OH -> V -PC -> F -VO -> H -SK -> S -PO -> O -KF -> N -NF -> V -NB -> C -PN -> O -FS -> C -PH -> F -VN -> S -OS -> V -HV -> H -HS -> B -SC -> C diff --git a/2021/day-14.ts b/2021/day-14.ts deleted file mode 100644 index 405f5ff..0000000 --- a/2021/day-14.ts +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -type Rules = Record; - -/** Counter for each pair how often it is known to exist */ -type State = Record; - -function processState(state: State, rules: Rules): State { - const result: State = {}; - for (const [pair, count] of Object.entries(state)) { - const insertion = rules[pair]; - if (insertion) { - const pair1 = pair.charAt(0) + insertion; - const pair2 = insertion + pair.charAt(1); - result[pair1] = (result[pair1] ?? 0) + count; - result[pair2] = (result[pair2] ?? 0) + count; - } else { - result[pair] = (result[pair] ?? 0) + count; - } - } - return result; -} - -function processTemplate( - template: string, - rules: Rules, - iterations: number -): number { - // Basic approach: We keep track of pairs and how often they exist in the string - // When processing we look at each pair. Either it matches a rule, in which case it produces (up to) two pairs, otherwise it gets copied literally. - // When counting characters we walk over all pairs, and count just the first character. As the last character of the input would not be recognizable - // then, we introduce an additional character at the end to make a pair out of that, too. - // Alternative approach: The last character will never change, so we could also simply bump the final counters by one for the last character. - - let state: State = {}; - - // Step 1: Split the initial template into a counter for the pairs - const templateWithEnd = `${template} `; - for (let i = 0; i < templateWithEnd.length - 1; i++) { - const pair = templateWithEnd.slice(i, i + 2); - state[pair] = (state[pair] ?? 0) + 1; - } - - // Step 2: Process the state for the given number of iterations - for (let i = 0; i < iterations; i++) { - const newState = processState(state, rules); - state = newState; - } - - // Step 3: Count the number of characters, and pick the lowest and highest - const counters: Record = {}; - for (const [pair, count] of Object.entries(state)) { - const c = pair.charAt(0); - counters[c] = (counters[c] ?? 0) + count; - } - const [maxCount, minCount] = Object.entries(counters).reduce( - ([max, min], [_, count]) => [ - Math.max(max, count), - Math.min(min, count), - ], - - [0, Number.MAX_SAFE_INTEGER] - ); - return maxCount - minCount; -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - const rules: Rules = {}; - let template: string; - - return new Promise((resolve, reject) => { - rl.on('line', (line) => { - if (!line) { - return; - } - - const [pair, insert] = line.split(/ -> /); - if (!insert) { - template = line; - } else { - rules[pair] = insert; - } - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - const indicatorPart1 = processTemplate(template, rules, 10); - const indicatorPart2 = processTemplate(template, rules, 40); - console.log( - `Results for ${input}: after 10 iterations = ${indicatorPart1}, after 40 iterations = ${indicatorPart2}` - ); - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = ['-example', '']; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-2-example.input b/2021/day-2-example.input deleted file mode 100644 index 0ed302d..0000000 --- a/2021/day-2-example.input +++ /dev/null @@ -1,6 +0,0 @@ -forward 5 -down 5 -forward 8 -up 3 -down 8 -forward 2 \ No newline at end of file diff --git a/2021/day-2.input b/2021/day-2.input deleted file mode 100644 index ba22f2f..0000000 --- a/2021/day-2.input +++ /dev/null @@ -1,1000 +0,0 @@ -forward 9 -forward 7 -down 7 -down 3 -forward 2 -forward 3 -forward 7 -down 6 -forward 7 -down 7 -forward 9 -down 9 -up 2 -down 5 -up 1 -forward 5 -forward 6 -up 4 -down 3 -down 4 -down 5 -up 6 -down 3 -forward 6 -forward 4 -down 4 -forward 5 -down 2 -up 1 -up 8 -down 1 -down 6 -forward 8 -down 4 -forward 8 -forward 6 -forward 2 -forward 2 -forward 3 -forward 8 -up 9 -up 2 -down 3 -up 3 -forward 5 -forward 2 -up 5 -forward 9 -down 7 -down 2 -up 7 -down 4 -down 6 -up 2 -down 9 -forward 7 -down 8 -forward 6 -up 1 -forward 6 -forward 4 -down 5 -forward 6 -down 8 -down 3 -forward 7 -down 8 -up 7 -down 1 -up 1 -forward 9 -down 7 -up 3 -down 6 -down 6 -down 6 -down 7 -down 9 -down 6 -down 9 -down 8 -down 3 -down 7 -down 3 -up 8 -down 5 -down 9 -up 4 -forward 5 -forward 5 -forward 2 -up 1 -forward 6 -down 6 -down 2 -forward 1 -forward 8 -down 4 -down 1 -down 8 -down 7 -forward 6 -forward 8 -down 8 -up 1 -up 1 -forward 1 -forward 3 -up 8 -down 1 -forward 4 -down 3 -forward 3 -forward 4 -forward 3 -down 3 -down 9 -down 3 -up 6 -forward 6 -forward 8 -forward 2 -up 1 -up 4 -up 4 -down 2 -down 2 -down 2 -forward 7 -up 9 -down 9 -up 1 -down 5 -forward 4 -down 2 -down 4 -forward 3 -down 7 -down 9 -forward 1 -up 5 -down 5 -down 5 -forward 2 -down 6 -forward 8 -up 4 -forward 6 -up 1 -down 4 -forward 2 -down 9 -forward 5 -down 7 -down 8 -down 9 -forward 6 -up 6 -forward 9 -forward 9 -down 7 -forward 7 -forward 5 -up 9 -forward 3 -down 9 -down 1 -down 8 -down 4 -forward 5 -forward 6 -forward 8 -forward 8 -down 4 -down 3 -down 8 -forward 3 -down 6 -down 8 -down 2 -up 8 -up 9 -down 6 -forward 3 -down 4 -down 6 -forward 9 -forward 6 -up 2 -down 8 -forward 2 -down 7 -forward 9 -up 9 -down 9 -down 2 -forward 9 -down 4 -down 9 -up 4 -forward 6 -down 2 -down 9 -forward 8 -forward 2 -up 8 -forward 9 -forward 2 -forward 3 -down 2 -up 3 -forward 9 -down 6 -down 3 -down 1 -forward 9 -forward 8 -down 9 -up 7 -down 8 -up 7 -forward 1 -forward 1 -forward 7 -down 2 -down 1 -up 1 -up 6 -down 5 -up 9 -up 7 -forward 1 -forward 6 -forward 1 -up 4 -down 6 -forward 2 -up 7 -down 2 -up 8 -forward 9 -forward 6 -forward 3 -forward 8 -down 1 -forward 8 -up 3 -forward 1 -forward 1 -up 9 -down 1 -down 8 -down 2 -forward 8 -down 8 -forward 7 -down 5 -forward 8 -forward 3 -forward 6 -forward 7 -up 5 -down 5 -forward 8 -down 2 -forward 3 -down 4 -down 9 -forward 6 -forward 5 -up 4 -forward 7 -down 3 -forward 9 -forward 5 -down 3 -up 5 -forward 4 -forward 8 -down 7 -up 2 -forward 7 -down 5 -up 2 -down 9 -forward 4 -down 3 -forward 5 -forward 4 -down 3 -forward 6 -up 1 -forward 8 -down 1 -up 7 -forward 8 -up 1 -up 1 -forward 2 -down 8 -forward 4 -forward 8 -up 6 -forward 5 -forward 7 -up 6 -up 4 -up 6 -down 1 -forward 3 -down 1 -down 1 -down 8 -forward 8 -down 5 -down 5 -forward 5 -forward 9 -down 9 -forward 7 -down 3 -down 5 -forward 6 -down 1 -down 5 -up 8 -down 9 -forward 3 -down 6 -up 2 -down 2 -forward 2 -up 2 -forward 8 -down 2 -forward 9 -forward 2 -down 7 -down 5 -forward 1 -forward 7 -up 6 -up 8 -forward 8 -forward 8 -up 3 -forward 8 -down 6 -down 6 -forward 4 -down 8 -down 5 -down 7 -forward 1 -forward 9 -forward 9 -up 5 -down 9 -down 1 -forward 4 -forward 1 -up 9 -forward 6 -down 6 -forward 2 -up 6 -forward 9 -up 1 -down 2 -up 3 -forward 2 -forward 1 -forward 6 -down 9 -up 1 -forward 7 -up 3 -forward 6 -forward 6 -up 2 -down 8 -forward 4 -down 4 -forward 2 -forward 2 -down 4 -down 7 -down 4 -down 5 -forward 3 -down 1 -forward 1 -forward 8 -down 7 -up 1 -forward 7 -forward 2 -down 9 -down 2 -up 2 -forward 3 -down 4 -down 7 -down 8 -forward 4 -forward 5 -forward 3 -up 3 -down 6 -forward 4 -forward 4 -forward 8 -forward 1 -up 2 -up 3 -down 4 -up 9 -forward 1 -forward 1 -forward 9 -down 2 -down 5 -up 9 -down 7 -down 9 -down 2 -down 4 -forward 1 -forward 1 -forward 8 -down 9 -down 6 -forward 2 -up 3 -down 8 -forward 1 -forward 8 -forward 4 -up 7 -forward 5 -forward 2 -forward 2 -up 8 -down 5 -forward 6 -down 3 -up 5 -forward 8 -forward 3 -forward 9 -down 1 -down 3 -forward 8 -down 2 -forward 6 -forward 2 -down 3 -down 3 -forward 6 -forward 4 -forward 7 -forward 2 -up 7 -up 4 -up 6 -forward 9 -down 3 -down 3 -up 7 -down 4 -up 3 -up 3 -down 5 -forward 1 -up 3 -down 1 -forward 2 -up 9 -forward 7 -down 6 -forward 4 -forward 8 -up 1 -forward 6 -down 7 -down 4 -up 9 -forward 4 -down 7 -up 1 -forward 9 -down 4 -down 7 -forward 1 -down 6 -down 6 -forward 3 -up 8 -forward 3 -down 1 -down 5 -down 8 -forward 2 -up 5 -forward 2 -up 7 -forward 5 -forward 1 -forward 3 -forward 4 -forward 5 -up 1 -forward 9 -down 5 -down 7 -up 9 -down 9 -forward 7 -up 6 -up 7 -forward 2 -forward 1 -up 4 -forward 6 -forward 9 -down 1 -forward 4 -down 5 -forward 4 -down 3 -down 5 -forward 6 -forward 3 -down 3 -down 8 -down 2 -down 4 -down 6 -down 4 -forward 2 -up 9 -down 3 -forward 1 -forward 9 -forward 5 -forward 5 -forward 9 -up 1 -down 4 -down 4 -up 7 -down 3 -up 3 -up 4 -forward 3 -forward 1 -forward 8 -up 6 -down 8 -down 4 -forward 7 -forward 9 -forward 2 -forward 8 -up 2 -down 4 -down 5 -forward 9 -down 6 -down 7 -down 8 -up 8 -forward 3 -forward 7 -forward 8 -up 2 -down 9 -down 6 -forward 3 -forward 4 -down 4 -forward 2 -up 6 -forward 1 -forward 7 -down 2 -down 1 -forward 2 -forward 2 -down 2 -forward 2 -forward 7 -up 4 -down 3 -forward 9 -down 7 -down 7 -down 6 -forward 3 -forward 9 -down 9 -forward 2 -down 5 -down 4 -down 9 -up 9 -down 6 -down 8 -down 1 -forward 8 -up 4 -up 4 -down 8 -forward 6 -down 2 -forward 4 -forward 3 -forward 2 -forward 4 -down 4 -forward 6 -down 9 -up 7 -up 5 -down 7 -down 4 -up 3 -forward 4 -down 9 -forward 6 -forward 4 -forward 4 -down 9 -forward 3 -forward 2 -up 7 -forward 3 -down 1 -down 3 -up 5 -down 8 -down 3 -down 4 -forward 7 -forward 9 -up 2 -forward 3 -up 4 -down 5 -up 3 -up 9 -down 6 -down 2 -down 5 -up 4 -up 6 -forward 4 -forward 6 -up 5 -up 5 -forward 8 -down 6 -forward 6 -down 7 -down 5 -down 3 -down 8 -forward 6 -forward 9 -forward 9 -up 9 -down 3 -up 5 -forward 4 -down 7 -forward 5 -down 7 -down 4 -forward 2 -forward 9 -down 8 -up 3 -up 7 -down 7 -up 7 -forward 3 -down 2 -forward 7 -down 4 -forward 1 -down 6 -forward 1 -up 4 -down 7 -up 3 -forward 7 -forward 5 -forward 7 -forward 6 -up 2 -down 4 -down 8 -down 4 -up 3 -forward 3 -up 3 -up 3 -down 7 -down 2 -down 3 -forward 7 -down 6 -down 9 -up 1 -down 8 -down 6 -down 3 -up 2 -up 6 -forward 9 -forward 5 -forward 4 -forward 9 -down 9 -forward 2 -up 7 -down 4 -down 8 -up 2 -forward 6 -up 6 -up 4 -down 2 -forward 6 -forward 4 -up 3 -down 6 -forward 5 -forward 3 -up 4 -down 7 -down 2 -down 6 -up 7 -forward 2 -forward 1 -forward 3 -down 2 -forward 1 -forward 2 -forward 4 -down 2 -down 5 -down 7 -down 8 -down 1 -up 1 -up 1 -forward 9 -down 3 -down 1 -forward 4 -up 6 -up 8 -forward 7 -forward 9 -down 3 -forward 9 -down 9 -forward 6 -down 1 -forward 7 -down 9 -forward 1 -down 8 -forward 8 -up 7 -forward 4 -up 5 -up 9 -forward 1 -forward 4 -forward 3 -down 3 -down 8 -up 3 -forward 1 -up 5 -forward 5 -up 6 -forward 8 -forward 1 -down 7 -forward 2 -down 9 -forward 3 -forward 7 -forward 2 -down 4 -forward 2 -up 6 -down 7 -up 3 -forward 7 -down 8 -down 3 -forward 2 -up 7 -down 2 -down 8 -up 6 -forward 7 -forward 1 -down 3 -forward 2 -forward 8 -down 8 -forward 1 -down 7 -down 1 -up 5 -up 3 -forward 5 -down 5 -up 9 -up 9 -down 3 -up 3 -down 4 -down 6 -up 7 -forward 3 -up 5 -down 3 -forward 4 -down 1 -up 1 -up 6 -down 8 -forward 5 -up 2 -down 5 -forward 6 -forward 4 -forward 9 -down 9 -down 5 -forward 5 -down 7 -down 7 -down 8 -forward 3 -down 6 -forward 5 -forward 5 -down 6 -forward 3 -down 7 -up 4 -up 3 -down 5 -forward 9 -forward 9 -up 9 -down 1 -up 2 -up 3 -down 7 -forward 3 -down 7 -down 4 -down 5 -down 1 -down 4 -up 9 -forward 1 -up 8 -forward 7 -up 6 -down 1 -up 2 -forward 2 -up 9 -down 6 -forward 4 -down 2 -up 5 -forward 1 -forward 4 -down 6 -down 2 -up 8 -forward 2 -forward 8 -forward 4 -down 9 -up 3 -forward 5 -forward 9 -forward 4 -down 2 -up 4 -up 9 -down 5 -up 2 -forward 6 -up 2 -down 6 -up 5 -up 3 -up 9 -forward 8 -down 2 -forward 7 -up 8 -down 9 -forward 2 -forward 2 -down 6 -forward 9 -forward 2 -forward 8 -up 3 -forward 5 -down 4 -forward 2 -down 7 -up 6 -forward 7 -down 6 -down 8 -down 3 -up 4 -up 5 -down 2 -down 9 -forward 2 -down 7 -forward 2 -forward 3 -forward 9 -down 6 -down 1 -forward 6 -down 5 -forward 2 -down 5 -down 1 -forward 5 -down 4 -down 6 -down 5 -forward 9 -up 6 -up 5 -up 2 -down 1 -down 8 -forward 4 -down 2 -forward 5 -down 1 -forward 7 -down 8 -down 9 -down 7 -up 1 -forward 2 -up 8 -down 9 -down 2 -down 1 -down 9 -down 2 -down 5 -forward 9 -forward 1 -down 1 -forward 9 -forward 7 -down 6 -down 1 -down 7 -forward 4 -forward 1 -forward 4 -forward 5 -forward 5 -down 2 -forward 7 -forward 6 -forward 3 -forward 9 -up 1 -down 5 -down 4 -down 2 -forward 1 -up 7 -forward 2 diff --git a/2021/day-2.ts b/2021/day-2.ts deleted file mode 100644 index 152959b..0000000 --- a/2021/day-2.ts +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - return new Promise((resolve, reject) => { - let horizontalPosition = 0; - let aim = 0; - let depth = 0; - - rl.on('line', line => { - const [command, arg] = line.split(/ /); - const amount = Number(arg); - switch (command) { - case 'forward': - horizontalPosition += amount; - depth += aim * amount; - break; - case 'down': - aim += amount; - break; - case 'up': - aim -= amount; - break; - } - }); - rl.on('error', err => { - reject(err); - }); - rl.on('close', () => { - console.log(`Results for ${input}: ${horizontalPosition} * ${depth} = ${horizontalPosition * depth}`); - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - await processInput(inputFile); - } -} - -const INPUT_SPECS = [ - '-example', - '', -]; - -main(INPUT_SPECS.map(inputSpec => `${basename(process.argv[1], extname(process.argv[1]))}${inputSpec}.input`)).catch(err => console.error(err)); - diff --git a/2021/day-3-example.input b/2021/day-3-example.input deleted file mode 100644 index 665fd57..0000000 --- a/2021/day-3-example.input +++ /dev/null @@ -1,12 +0,0 @@ -00100 -11110 -10110 -10111 -10101 -01111 -00111 -11100 -10000 -11001 -00010 -01010 \ No newline at end of file diff --git a/2021/day-3.input b/2021/day-3.input deleted file mode 100644 index 29fa12f..0000000 --- a/2021/day-3.input +++ /dev/null @@ -1,1000 +0,0 @@ -011110111101 -110010010001 -111011111111 -110011010100 -111100000011 -010101001001 -010101000010 -100111101000 -110110101110 -001001101000 -101100100110 -101001100110 -101110000110 -011111111100 -110010000101 -000011111001 -101000110001 -100111011101 -011011011011 -111100000100 -010100101100 -110010000110 -101000001101 -010100110011 -111101101100 -100101000011 -101000100111 -111010010000 -011111000110 -110100101010 -011010000000 -101110100111 -010000001000 -001111001010 -001011101011 -100001110010 -001100100100 -111110011110 -000011101011 -101100111011 -000000101011 -101000000100 -001000101011 -110101000111 -011010111011 -100011101011 -110101011000 -001110110010 -100011101110 -001101011001 -000101100100 -010000101100 -100010001100 -100101001010 -011010110001 -111001110110 -111101111101 -000010011000 -110100111000 -011010000100 -000000010110 -100000001001 -110101101001 -111010100001 -101011110000 -110100101111 -010000010110 -111010110100 -011110010110 -001100001111 -001110001110 -111001110101 -010111000110 -101111001101 -010011010011 -000001110101 -101100010001 -111101110011 -101000010101 -100110011001 -010101011101 -111111101110 -010011010010 -110000101111 -100101111001 -011110100110 -111100110000 -100000111000 -011010011111 -101001101110 -110001110111 -101011001111 -010101110010 -000110001100 -101110011011 -000111111100 -001001011110 -010000100101 -110110111101 -001000011001 -011011110101 -100000001011 -010110000011 -110011001100 -110000110010 -111000110111 -110000001000 -011110101001 -001111101010 -001111000111 -100010100010 -001001010100 -001101101001 -000011000011 -101010101101 -101101011000 -000010001000 -011101110101 -000001011110 -001000101001 -000110000000 -100010111011 -001111111111 -001101110101 -001101100100 -101000011110 -010001010101 -111011010000 -000011011101 -101101001010 -010000110001 -111110011000 -110011100111 -000110111100 -010110001101 -010100010100 -101010100001 -011010111001 -010001100100 -010100111011 -010010010111 -011100011011 -101110110111 -011111101000 -101110001101 -001001100111 -101100101010 -100001010101 -100101000101 -101000000011 -110000101110 -001000111000 -011100000000 -101100111110 -000100101001 -010100111111 -000101110000 -101111100010 -110011101110 -011001000100 -111001001000 -000001111010 -100100010011 -101010101001 -010110010000 -110011110111 -101000010000 -100000101010 -110010011010 -001001001111 -001011011000 -011101100110 -100101101010 -110010111100 -110000100100 -010010001100 -010011010101 -110011000010 -101111110010 -001011010001 -001011001010 -100000001010 -000110010010 -000111101111 -110011101100 -110100110010 -100100010100 -010001100010 -001101101111 -111110110001 -111101000101 -000101101111 -000100110100 -001000111011 -011000111000 -101000011001 -110110110000 -111111111010 -000000001010 -000010101010 -001000001001 -101001100101 -001001000101 -101111110111 -101101001100 -001110111011 -101000111101 -010100000000 -110011011011 -000110100001 -100110111010 -000011100001 -010000010111 -110111011100 -111100001011 -001111011001 -000011011100 -111110011011 -010110000010 -001000010100 -011110011110 -111100001101 -110011100101 -011111110000 -100111011010 -000000111011 -111111001010 -010100111100 -000101111000 -110010011111 -110111101001 -100011000001 -111001100010 -100101000001 -010111111101 -110010110001 -001101001001 -100101101001 -011000110101 -101110011001 -101111101010 -100111010001 -011100111000 -001100000111 -001110011110 -010010000101 -010010110001 -111010001101 -000010110001 -010110101110 -011111111000 -100000101001 -111101011101 -000001010100 -000011001011 -110000011100 -000011001110 -110101010110 -011000110011 -000111111000 -100000110000 -001010101010 -001001101001 -011101011011 -100011110000 -111011011000 -111101110100 -000001010110 -100011110100 -101101000010 -000011011011 -101011110110 -100001101011 -010111100000 -000011000010 -000111001111 -011001100100 -110110010010 -000011110111 -101001001011 -010110110101 -001100000110 -000111101110 -110011010011 -101001010010 -010011110100 -110101011010 -101100101011 -101110010110 -010000000011 -010001101001 -101010011110 -010101100001 -100100000110 -000010010111 -101100101110 -000111000001 -110100111111 -010011100000 -011101110000 -011111011110 -101011011110 -100011110010 -001100011100 -011010010111 -101010011001 -110100100110 -001011100111 -001001101110 -010001001000 -101111100100 -101011010001 -100101100001 -010000101001 -000100000011 -101011101000 -000001100101 -110001101111 -001110000111 -010010000110 -101001101101 -100110011000 -100110000110 -000000110010 -000111100001 -001000101110 -110000000111 -110011101111 -101110010010 -110010001110 -101111011010 -000001000000 -110010100111 -100111010111 -001100101111 -001110111001 -111100011100 -011000010100 -100101101101 -100001001110 -111110100011 -101111001000 -010111000100 -110001110010 -001110101111 -101000000111 -010001010111 -000000000111 -010001111100 -011100000110 -010100010000 -101000010001 -101110000100 -111111110001 -110000001101 -111001111111 -000100011111 -111001101000 -001011111111 -110100001011 -111011000001 -001111101101 -101011110100 -101010110010 -101111110011 -011100100100 -001101011110 -000100001011 -100001011101 -101000010110 -001011110111 -110101000101 -011011011110 -001010000001 -000111000010 -100101001001 -000001110010 -110100010011 -111100101101 -100111011001 -000110101111 -101010000100 -011101011000 -001110000010 -001000111101 -110000011000 -010010010110 -100101011000 -000010010100 -110001101010 -101010000110 -111111010010 -001111001000 -110100101001 -010001000001 -001111110010 -110001011011 -111100000001 -011011110111 -111001001111 -110010000100 -100101111011 -001000111001 -111010001010 -101100100100 -101000111110 -000100101110 -111000101001 -001001010110 -100100101101 -111111011100 -111001110011 -011111001100 -101010101100 -000011010001 -110111001110 -010100000111 -110011100000 -101001000010 -000111101001 -010100011111 -011101001001 -100110010010 -100110101010 -010001110010 -011101000101 -001111100010 -011010111111 -110110001110 -010010010000 -101100110011 -111111011101 -000011000101 -100000111100 -111101010011 -100111010011 -110010011011 -000011111100 -011110011000 -101100000101 -111110000011 -100100001011 -000010011001 -111000011101 -111000110101 -110010100010 -101001010100 -010001110011 -001101001011 -010000101111 -111011100000 -000110000111 -000011100000 -000101011101 -000101100001 -011100100000 -011100001011 -011110111011 -111110010010 -111000010110 -000110001110 -111100011001 -010110000110 -000001010111 -100001111001 -100111100001 -011000111011 -111111101001 -001000000001 -001101100011 -111101010100 -001101110001 -110100111011 -000111011010 -000111110100 -010100000011 -010001110101 -101100000011 -110011111000 -010010101001 -101111011100 -101101101101 -111110000100 -001011000000 -010100001110 -001001011011 -011000011101 -110111110101 -101010010111 -110101000010 -111111000000 -101010101110 -101100110101 -100110001011 -011010110010 -000010110010 -000101001001 -000011110011 -101010111111 -011000101101 -111001100101 -000110101001 -110100000001 -110010000001 -111011011110 -101110110101 -000001111001 -100100011011 -011111111001 -100111101110 -101010010011 -000010110000 -011110111010 -000011110100 -101010010001 -110000011001 -100100110010 -100110100110 -110000110001 -100111010100 -000111011100 -110001000100 -011000010010 -101111111110 -011100011100 -000001001110 -111101101000 -110011001011 -010001000110 -000111000000 -000001001001 -100100011100 -101111011101 -000111001001 -010001011111 -001100100101 -011101000100 -011001110101 -100111100110 -010110000100 -111011100011 -110000011010 -011000101111 -100010100011 -111101001111 -000111010110 -011001110000 -101101011011 -010011000111 -110001101100 -000100001110 -110101111000 -111100001110 -100101011110 -111011101110 -110010101111 -110111101101 -110100011001 -000111111111 -011001101110 -001100010000 -110011110000 -011010110101 -011110111100 -100001110000 -110101101110 -000010001100 -011001101100 -100000110110 -100111110111 -101110001100 -010101000011 -110001110001 -011001011001 -011001111001 -111010011001 -110011011010 -001011011110 -111000000100 -101110111001 -110000111010 -101010110101 -110001011111 -011001011111 -101110010101 -010110110111 -010101100101 -010111111000 -010000011101 -100111010000 -100001111101 -001101111010 -001000000011 -010110111011 -010001110111 -000011001000 -110001111010 -111101001001 -110000000100 -111100001000 -111010000110 -000100011110 -110101101011 -001011110100 -011101011001 -110101010100 -110010011001 -100101001111 -100110110100 -000101001101 -001011101110 -101000001010 -001100101010 -100010011011 -100011100001 -000101011111 -111001100110 -101110101011 -111101111100 -001000001010 -001100010100 -111010100111 -000101110001 -001010100001 -001111110110 -110110101000 -110110000110 -011110111110 -100111110001 -011000001110 -110101010011 -010110001110 -111110010001 -100101111000 -001111100101 -110011001010 -111101010010 -111111000011 -001100101011 -100001101100 -100001110110 -110000000001 -000101001011 -111111110111 -000100010000 -101010110011 -111001101011 -010111100010 -001000011011 -010010110011 -001010111101 -010011011011 -011110000001 -010101011111 -001011101100 -010000010000 -111001100111 -111001010011 -111000111010 -001100011110 -010111011101 -010110000111 -010101100010 -011110011100 -100101000111 -011010000111 -000101010111 -100101001100 -011010110011 -011000011110 -010011110101 -111000101111 -111010101111 -101111010110 -100100101000 -101011111100 -100001001000 -000100010101 -001001100000 -110100100001 -100011110001 -101110110110 -110011000100 -011001000101 -111001110111 -111011010110 -101110110010 -100110111001 -110101011011 -110110000011 -000111101101 -100011010010 -111000100101 -010001100000 -010011111001 -010101010101 -110011110101 -100000100110 -110010101000 -000100110101 -010010110111 -111000001001 -001011111011 -010000111001 -111011001110 -011101110110 -010001111001 -111001111110 -101010101111 -101111111101 -110011101010 -010011000110 -101001111010 -101110000101 -000010000110 -111110000111 -001010111011 -010110011111 -001011101101 -011101011110 -000010000010 -101011010011 -011100011000 -111000100011 -011111011111 -110000001010 -000100000100 -101010111101 -110000111000 -001100110000 -111111011010 -110100110000 -000000000000 -101001000000 -110010110101 -011011001100 -101101101110 -010110100011 -101111000000 -111011100101 -110100100010 -010111000001 -110110011000 -011101111110 -000010110110 -111000000011 -001101110010 -100000110011 -000110000011 -100111110000 -011110110011 -111010101010 -010010001011 -101111000110 -001010000011 -101111010000 -011000111001 -001001111101 -010100011001 -000000010011 -001111001001 -011000010000 -011001111111 -100010101001 -010000100011 -111111101101 -011011001000 -011001010011 -111011011001 -010001110110 -110010110000 -000000000011 -110110000000 -011101001101 -011010000101 -101011100110 -001101010010 -100000000100 -100100010001 -100110011111 -111100001010 -001100011111 -000100000110 -011011010010 -011010001100 -011111101011 -011010101001 -110111000110 -110000110110 -011110110000 -010011011101 -010011100100 -000110111001 -111011111001 -101111010010 -011000111100 -101111111010 -110011000001 -000100011000 -110101110100 -011001101010 -100011011101 -001011110011 -110010111110 -000110001101 -111011101001 -100110100001 -101011011010 -001000101010 -101011100111 -110110000001 -100100000010 -101100010011 -111001010101 -011100000101 -100010111100 -010110100010 -100100110001 -100111001001 -011101010010 -101101111000 -111100100111 -111011001000 -100111011111 -111001100001 -010001111011 -011110100100 -111111010101 -101011111110 -110101101100 -000100101111 -011110001000 -101101001110 -001111111010 -110011100110 -110110011100 -111111100000 -000000010001 -100100001101 -101000101110 -100001011010 -100011000100 -110011110110 -000000110100 -010110001010 -101000110000 -110110001001 -000001000101 -011111100111 -000011110101 -101111010101 -010101001111 -110111001111 -101001110010 -011001010111 -101000101010 -100100000111 -100011001011 -110010000000 -001000110001 -100010001101 -010001000010 -101101111111 -111001001011 -101001011100 -000100111100 -110000000101 -101010011101 -000101000111 -111000101100 -001100000100 -010010100101 -011010100010 -111000100110 -001001111010 -101001001111 -011000100011 -011000001100 -011110101111 -111011111110 -101001001010 -010000001111 -000000000101 -000111001010 -100001000111 -111101010001 -010011001111 -001110010000 -101101001001 -000110110111 -001101011011 -111100100010 -101010001000 -001001101100 -011110001101 -000101000011 -111101100111 -100110000010 -111010100101 -011010011110 -000000101000 -001011001000 -001001011010 -011100000100 -000011010101 -111110011100 -001101110110 -100011101111 -011001110010 -011100100111 -010101001100 -000101010000 -101001101001 -100101110111 -101101100110 -000101100010 -111011000011 -010010010011 -000111111110 -010101100011 -000001010010 -111100110010 -101011001010 -010110011110 -011001101111 -011100001010 -001111001100 -000110100011 -101011101010 -011111111110 -100011011011 -101010011111 -010001110001 -100010101101 -010101010011 -100001010001 -111010011000 -011110100010 -001111000101 -111101101010 -011110100000 -111110001101 -110010010100 -000001010011 -000100101100 -111000111111 -011111000011 -010000011001 -000110001011 -111100101110 -001000110101 -001011111100 -001111010001 -101000100101 -000101001100 -000110101010 -010010011111 -111101001000 -101110110011 -111100100110 -101010101011 -101010101010 -100000111001 -000101000001 -100010010101 -011000101000 -100100001111 -110111100011 -101100000000 -001011110001 -110011001111 -000001000011 -001100111011 -101100010000 -001111000001 -111100000101 -101010111011 -011111110010 -011111010001 -101011010100 -000111111011 -110000100110 -110111110000 -100101101110 -001011000001 -101100001101 -011100010010 -000110100110 -010101110111 -111100101011 -101101001101 -011011111110 -011100011001 -110010011100 -000001011100 -101110100110 -010001011100 -011111001010 -100111100101 -111111000010 diff --git a/2021/day-3.ts b/2021/day-3.ts deleted file mode 100644 index 530a638..0000000 --- a/2021/day-3.ts +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -/** - * Complete report - * - * - String values must have the same length - * - String values must only contain '0' and '1' characters - */ -type Report = string[]; -type Counter = [zeros: number, ones: number]; -type Counters = Counter[]; - -function selectMostCommon([zeros, ones]: Counter, ifEqual: number) { - if (zeros === ones) { - return ifEqual; - } else { - return zeros > ones ? 0 : 1; - } -} - -function selectLeastCommon([zeros, ones]: Counter, ifEqual: number) { - if (zeros === ones) { - return ifEqual; - } else { - return zeros > ones ? 1 : 0; - } -} - -function createPowerRate(counters: Counters, select: (counter: Counter) => number): number { - let result = 0; - let shift = 0; - for (let i = 0; i < counters.length; i++) { - const bit = select(counters[i]); - result |= (bit << shift); - shift++; - } - return result; -} - -function updateCounters(counters: Counters, value: string) { - // Value is a string of '0'/'1' characters, exactly as many as there are counters - // (otherwise we would have to apply magic to backfill them if the length changes, which our - // input doesn't have.) - Array.from(value).forEach((c: string, index) => { - if (c !== '0' && c !== '1') { - throw new Error(`Not a valid value: ${value}`); - } - counters[value.length - index - 1][Number(c)]++; - }); -} - -function toCounters(report: Report): Counters { - const counters: Counters = []; - - for (const value of report) { - // Initialize on the first value - if (counters.length === 0) { - for (let i = 0; i < value.length; i++) { - counters.push([0, 0]); - } - } else if (counters.length !== value.length) { - throw new Error(`Change in length not supported`); - } - - updateCounters(counters, value); - } - return counters; -} - - -/** - * Filter the report at `position` using `select` and return a new report - * - * @param report - * @param counters - * @param position - */ - function filterReport(report: Report, counters: Counters, position: number, select: (counter: Counter) => number): Report { - // NB: Counters are LSB->MSB, but position is MSB->LSB - const counter = counters[counters.length - position - 1]; - // Select the value to keep - const bit = select(counter); - const result: Report = []; - for (let i = 0; i < report.length; i++) { - const value = report[i]; - if (value[position] === `${bit}`) { - result.push(value); - } - } - - return result; -} - -function createLifeSupportRating(report: Report, select: (counter: Counter) => number): number { - if (report.length === 0) { - throw new Error('Report is empty'); - } - const bits = report[0].length; - - let position = 0; - let workReport = [...report]; - while (workReport.length !== 1 && position < bits) { - const counters = toCounters(workReport); - workReport = filterReport(workReport, counters, position, select); - position++; - } - - if (workReport.length === 1) { - return parseInt(workReport[0], 2); - } else if (workReport.length === 0) { - throw new Error('No matching numbers'); - } else { - throw new Error('Too many matching numbers'); - } -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - return new Promise((resolve, reject) => { - const report: Report = []; - - rl.on('line', line => { - report.push(line); - }); - rl.on('error', err => { - reject(err); - }); - rl.on('close', () => { - const counters = toCounters(report); - // NB: For the power rates the `ifEqual` case in the selector should not happen, the `-1` will trigger an error. - const gammaRate = createPowerRate(counters, counter => selectMostCommon(counter, -1)); - const epsilonRate = createPowerRate(counters, counter => selectLeastCommon(counter, -1)); - const oxygenGeneratorRating = createLifeSupportRating(report, counter => selectMostCommon(counter, 1)); - const co2ScrubberRating = createLifeSupportRating(report, counter => selectLeastCommon(counter, 0)); - console.log(`Results for ${input}: power consumption = ${gammaRate} * ${epsilonRate} = ${gammaRate * epsilonRate}, life support rating = ${oxygenGeneratorRating} * ${co2ScrubberRating} = ${oxygenGeneratorRating * co2ScrubberRating}`); - - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - '-example', - '', -]; - -main(INPUT_SPECS.map(inputSpec => `${basename(process.argv[1], extname(process.argv[1]))}${inputSpec}.input`)).catch(err => console.error(err)); diff --git a/2021/day-4-example.input b/2021/day-4-example.input deleted file mode 100644 index 49d17bc..0000000 --- a/2021/day-4-example.input +++ /dev/null @@ -1,19 +0,0 @@ -7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 - -22 13 17 11 0 - 8 2 23 4 24 -21 9 14 16 7 - 6 10 3 18 5 - 1 12 20 15 19 - - 3 15 0 2 22 - 9 18 13 17 5 -19 8 7 25 23 -20 11 10 24 4 -14 21 16 12 6 - -14 21 17 24 4 -10 16 15 9 19 -18 8 23 26 20 -22 11 13 6 5 - 2 0 12 3 7 \ No newline at end of file diff --git a/2021/day-4.input b/2021/day-4.input deleted file mode 100644 index 2354ec0..0000000 --- a/2021/day-4.input +++ /dev/null @@ -1,601 +0,0 @@ -90,4,2,96,46,1,62,97,3,52,7,35,50,28,31,37,74,26,59,53,82,47,83,80,19,40,68,95,34,55,54,73,12,78,30,63,57,93,72,77,56,91,23,67,64,79,85,84,76,10,58,0,29,13,94,20,32,25,11,38,89,21,98,92,42,27,14,99,24,75,86,51,22,48,9,33,49,18,70,8,87,61,39,16,66,71,5,69,15,43,88,45,6,81,60,36,44,17,41,65 - -76 82 2 92 53 -74 33 8 89 3 -80 27 72 26 91 -30 83 7 16 4 -20 56 48 5 13 - -67 7 75 66 4 -35 97 21 29 95 -58 98 56 71 65 -55 61 19 64 9 -38 34 42 30 2 - -79 97 63 98 75 - 1 13 0 76 46 -56 59 58 55 86 -43 27 73 67 31 -33 81 26 19 3 - - 3 37 33 8 19 -34 69 82 9 51 -56 45 15 85 79 -32 55 81 22 12 -42 20 48 7 75 - -16 68 45 31 54 -57 40 77 5 76 -67 24 84 14 41 -21 23 27 36 7 -56 8 86 50 22 - -28 53 81 26 40 -59 29 49 89 48 -10 44 3 42 7 -79 87 32 31 54 -15 23 65 69 56 - -86 20 47 1 94 - 3 91 77 14 83 -79 93 4 92 65 - 0 67 30 36 7 - 6 48 59 35 73 - -75 87 7 28 25 -31 71 35 52 32 -47 99 0 80 33 -41 59 24 50 17 -93 58 26 81 53 - -41 77 15 55 86 -20 5 54 79 93 - 3 61 57 47 7 -85 98 91 39 13 - 4 81 63 72 24 - -27 37 57 38 72 -86 99 14 2 15 -94 25 73 13 54 -19 26 56 3 7 - 1 49 33 24 21 - -11 79 12 89 1 -23 98 49 66 48 -15 30 90 57 31 -55 47 61 9 74 -76 93 81 63 95 - -51 92 84 77 26 -85 42 80 89 25 -82 41 73 58 49 - 6 36 75 4 40 -62 11 56 24 69 - -19 79 35 75 18 - 7 4 12 78 70 -44 52 26 94 60 -71 65 61 89 87 -83 95 73 93 13 - -36 79 62 91 58 -12 46 9 55 93 -98 32 68 87 69 -27 90 51 45 2 -15 43 29 26 40 - -29 47 78 54 31 -98 65 71 8 72 -75 51 13 80 2 -93 69 20 52 96 -33 91 3 37 62 - -94 74 2 23 71 -16 95 52 31 80 - 3 4 28 9 50 - 6 40 47 62 48 -97 43 85 11 99 - -20 64 23 36 39 -22 31 75 45 24 -53 19 17 58 51 -66 4 81 72 37 -34 82 42 91 48 - -22 15 43 97 13 -73 71 88 1 48 -84 4 29 87 95 -90 40 11 67 6 -23 10 12 64 99 - -29 61 2 34 89 -93 87 10 42 65 -13 45 88 30 69 -71 78 1 20 19 -44 75 9 84 37 - -48 89 80 68 45 -81 12 1 64 77 -79 87 21 26 40 -44 82 46 78 54 -33 63 8 0 98 - - 0 62 13 43 93 -11 66 99 86 55 -27 89 51 98 46 -39 76 73 24 37 -23 68 72 80 64 - -37 89 58 78 76 -41 9 22 97 82 -40 39 73 96 8 -91 4 84 35 34 -70 12 79 75 7 - -26 18 12 88 97 -10 51 62 53 79 -24 47 31 89 21 -57 96 1 17 80 -58 92 7 14 60 - -12 23 6 71 64 -82 40 15 18 29 -53 21 76 52 84 -32 86 89 22 91 -74 58 80 2 63 - -71 96 10 39 87 -45 68 94 76 33 -59 60 11 62 88 -13 37 63 47 7 -44 79 24 21 16 - -80 71 39 36 1 - 9 23 55 58 91 -65 60 19 25 22 - 0 88 98 83 93 -82 69 43 78 8 - -67 80 42 49 97 - 7 18 92 98 89 -21 95 61 8 64 -76 63 52 68 87 -47 34 84 45 96 - -40 0 45 33 79 -18 56 83 6 58 -66 7 4 25 61 -91 46 60 22 99 -62 65 64 84 17 - -68 18 96 88 61 -89 55 81 20 70 -60 76 17 69 40 -37 63 41 54 11 -43 94 58 47 31 - -60 63 64 26 21 -87 99 49 11 16 -70 41 50 1 38 -45 98 94 67 62 -13 34 61 92 40 - -56 64 37 26 34 -69 16 72 75 77 -19 8 50 38 98 - 0 2 99 48 20 -68 35 88 57 90 - -17 41 40 48 54 -67 52 63 25 78 -95 26 12 85 37 -69 93 58 62 11 -47 33 14 35 81 - -26 51 80 31 64 - 2 7 59 37 57 -70 78 52 91 50 -86 0 15 20 25 -85 79 41 98 83 - -91 86 31 63 4 -81 37 77 94 74 -45 95 88 23 40 -29 46 79 18 70 -75 14 20 51 68 - -30 59 37 56 99 -74 14 4 21 53 -61 49 84 40 33 -20 51 79 66 27 -58 23 88 17 75 - -46 64 31 6 61 -38 14 77 83 59 -13 81 91 17 24 -11 96 90 10 49 -73 82 1 69 45 - -21 57 79 10 41 -67 74 96 20 94 -29 40 78 9 85 -23 25 49 0 39 -59 88 58 86 92 - - 1 22 49 43 32 -47 56 18 16 25 -42 57 48 53 46 -78 20 89 36 96 -24 28 76 39 29 - -53 66 38 11 94 -49 27 25 1 82 -12 72 50 61 51 -97 92 96 4 89 -47 44 21 24 81 - -16 70 78 12 63 -87 32 95 99 64 -68 54 85 53 94 -88 22 52 3 23 -48 27 1 58 31 - -71 62 41 44 49 -67 98 61 48 46 -47 9 24 30 51 -29 76 57 53 34 -23 96 42 5 73 - -50 72 56 97 2 -20 5 3 55 93 -24 7 22 9 96 -58 60 38 17 36 -11 54 79 28 53 - -13 21 35 79 91 - 8 28 68 54 6 - 0 25 82 78 1 -29 99 41 46 95 -66 72 17 55 76 - -43 42 7 85 90 -91 80 79 72 8 -34 77 44 30 92 -48 49 40 70 86 -28 69 27 84 73 - -17 94 67 26 63 -68 77 71 23 13 - 6 96 11 21 73 -53 33 80 62 99 -60 36 38 32 75 - -75 83 50 32 29 -61 94 4 35 51 -52 77 54 69 5 -36 89 76 26 71 -74 19 13 33 18 - -29 24 28 5 54 -56 86 37 45 83 -34 77 42 58 76 -82 1 4 39 64 -61 26 99 72 89 - -25 80 23 88 2 -76 93 90 86 52 -17 62 55 83 7 -57 81 24 0 99 -67 44 27 4 94 - -71 26 62 63 31 - 4 15 38 0 89 -41 77 34 42 19 -39 90 45 30 73 - 3 33 8 50 55 - -65 26 20 8 70 -96 24 88 29 46 -22 6 21 4 72 -59 32 18 49 61 -28 58 66 67 92 - -68 45 62 77 40 -53 1 21 11 83 -44 88 81 56 89 -29 32 47 0 50 -26 74 78 59 6 - -52 56 23 84 74 -64 21 45 35 75 -82 86 60 97 83 -69 78 15 20 37 -68 36 17 43 28 - -92 33 36 48 34 -75 77 79 39 88 -61 28 21 2 94 -84 89 17 22 67 -38 41 7 80 12 - -27 34 91 21 87 - 5 65 7 70 36 -31 3 38 49 61 -96 62 50 97 20 -47 37 16 59 76 - -39 50 3 25 31 -37 36 88 40 14 -26 70 75 30 9 -97 42 86 90 20 -38 66 22 4 69 - -62 64 72 11 79 -50 0 89 30 70 -83 53 93 39 22 -90 20 80 55 32 - 6 12 19 27 2 - -17 85 24 50 13 -12 41 75 74 35 - 3 88 69 73 1 -77 34 71 32 44 -96 26 37 46 9 - -84 20 33 4 21 - 5 22 19 91 51 -23 56 44 43 68 - 6 50 70 47 46 -75 81 34 32 13 - - 6 36 27 32 59 - 4 75 63 86 48 -81 49 44 7 25 - 0 69 11 43 91 -87 39 23 47 98 - -53 16 97 94 69 - 4 43 9 67 33 -21 83 32 87 35 -55 78 68 28 75 -51 19 82 54 24 - -50 84 63 21 92 -51 52 97 66 1 -22 44 31 64 49 -83 24 2 35 45 -15 16 71 60 58 - -54 83 48 63 2 -43 82 65 20 42 -52 86 58 27 75 - 7 76 64 18 11 -77 93 67 0 25 - -12 60 93 99 37 -29 44 47 4 89 -30 63 52 66 91 - 2 38 72 84 6 - 1 96 5 18 33 - -76 61 58 41 43 -21 69 55 18 79 -40 59 9 7 36 -77 82 47 84 89 -92 13 49 6 62 - -33 68 74 92 24 -28 3 15 77 37 -83 72 21 71 29 -88 64 47 35 44 -51 18 31 95 99 - -71 50 97 18 77 -29 30 0 88 49 -98 99 95 11 1 -46 83 64 55 56 - 9 6 59 87 19 - -71 41 13 33 4 -23 22 26 28 82 -95 62 7 34 64 -10 68 14 21 37 -73 53 88 81 1 - -16 87 61 58 95 -90 27 3 65 38 -35 17 85 6 47 -69 22 54 83 82 -28 67 96 48 88 - -17 47 81 13 77 -64 86 82 62 24 -40 41 52 50 15 - 4 71 2 90 22 -61 38 20 78 34 - -65 51 54 10 16 -52 28 68 75 8 -26 97 96 49 73 -95 17 64 80 34 - 5 76 25 66 77 - -30 10 42 72 75 -67 85 36 64 25 -61 48 59 96 98 -81 89 3 4 46 -33 84 32 78 80 - -93 24 5 21 95 -18 1 66 57 31 - 2 17 62 8 28 -73 10 38 25 63 -91 71 48 44 4 - -92 54 34 5 74 - 8 31 94 24 44 -43 2 64 49 21 -73 19 99 60 78 - 0 23 16 86 85 - -25 34 6 67 71 -79 76 39 81 32 -23 36 82 92 50 -10 51 55 40 80 -20 44 30 24 28 - -74 22 58 26 10 -36 43 76 93 15 -87 55 6 91 37 -81 86 8 99 30 -78 62 50 44 54 - -16 14 79 80 42 -27 83 26 82 29 -43 76 9 66 5 -75 77 99 45 10 - 2 61 32 73 91 - -16 60 83 81 47 -23 27 59 85 24 -75 33 36 86 15 -70 91 55 93 63 -25 32 53 14 82 - -98 87 40 52 0 -86 58 74 2 84 -24 99 61 41 92 -77 17 1 43 57 -62 70 94 89 19 - - 7 18 19 85 98 -40 0 99 45 63 -59 49 37 42 5 -58 82 25 53 4 - 2 1 62 68 33 - -21 87 18 29 34 -53 24 26 67 25 -49 77 4 64 59 -52 12 97 2 36 -66 76 9 74 95 - -92 44 14 18 48 -31 74 79 86 58 -68 12 33 55 56 -97 94 25 41 65 -29 36 53 60 62 - -23 26 85 88 7 -96 1 75 76 9 -49 44 18 78 59 -64 83 19 30 74 -52 95 66 62 22 - -43 99 38 73 33 -36 46 24 32 91 -47 68 15 5 81 -37 20 0 97 50 -12 30 53 4 55 - -26 33 49 91 30 -61 22 7 12 82 - 4 36 1 6 11 -96 14 35 90 50 -97 25 28 32 58 - -92 36 56 10 62 -73 35 60 25 34 -96 24 16 53 84 -37 51 30 58 1 -20 80 43 63 45 - -39 68 53 30 91 -11 97 10 12 55 - 6 76 57 77 48 -56 51 98 71 82 -46 27 54 33 5 - -19 38 63 64 61 -48 28 29 60 72 -99 94 55 25 76 -98 37 7 3 80 -10 2 16 35 50 - -16 68 75 19 58 -28 21 56 11 46 -60 25 32 88 30 -53 62 69 7 91 -73 94 24 6 38 - -69 4 37 70 54 -67 17 2 57 16 -72 30 43 58 1 - 6 56 28 86 18 - 7 94 55 35 77 - -73 32 57 79 1 -89 17 26 44 29 -11 86 94 38 74 -49 98 54 76 6 -67 45 87 21 51 - -14 73 22 48 69 -78 89 4 32 18 -96 59 26 43 92 -68 33 97 53 35 -61 52 87 57 31 - -86 1 22 31 20 -14 84 23 38 18 -57 67 5 90 6 -91 21 52 65 36 -61 56 3 51 25 - -60 5 98 31 76 - 3 44 24 16 63 - 0 96 56 25 84 -88 18 71 93 19 -26 77 86 23 65 - -62 58 11 34 26 -35 56 97 67 90 -20 65 27 73 77 - 4 84 19 82 45 -43 92 18 68 55 - -33 46 21 41 75 -98 73 67 80 81 -84 16 44 93 94 - 1 9 26 97 52 -88 74 12 95 99 - -46 83 30 22 79 -72 26 42 74 33 -54 41 94 86 82 -27 81 31 34 12 -77 6 38 56 71 - -22 80 82 60 24 -20 49 51 58 59 -47 35 67 92 78 -15 8 71 97 63 -37 27 98 16 38 - -71 94 59 27 83 -81 68 58 61 43 -12 75 93 70 56 -19 28 99 39 20 -18 22 34 78 13 - -43 70 54 13 60 -17 24 31 47 84 -88 15 40 45 76 - 7 78 63 75 56 -23 66 96 26 46 - - 2 16 13 57 32 -26 70 37 50 68 -58 17 3 96 67 -33 95 72 59 42 -94 43 51 20 60 \ No newline at end of file diff --git a/2021/day-4.ts b/2021/day-4.ts deleted file mode 100644 index 6ff8b09..0000000 --- a/2021/day-4.ts +++ /dev/null @@ -1,175 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -type Board = number[][]; - -function parseBoard(lines: string[]): Board { - const result: Board = []; - for (const line of lines) { - const row = line - .trim() - .split(/\s+/) - .map((s) => parseInt(s, 10)); - if (row.length !== lines.length) { - throw new Error( - `Expected row with ${lines.length} numbers, got "${line}"` - ); - } - result.push(row); - } - return result; -} - -function printBoard(board: Board, marks?: boolean[][]) { - for (let rowIndex in board) { - const row = board[rowIndex]; - console.log( - row - .map((n, columnIndex) => { - const symbol = marks?.[rowIndex][columnIndex] ? 'X' : n; - return String(symbol).padStart(4); - }) - .join(' ') - ); - } - console.log(); -} - -function updateMarks(n: number, board: Board, marks: boolean[][]): boolean { - // Walk over all elements of the board, update the marks, and return whether - // bingo was achieved. - let result = false; - const columnBingos: boolean[] = new Array(board.length).fill(true); - for (let rowIndex in board) { - let rowBingo = true; - for (let columnIndex in board) { - const at = board[rowIndex][columnIndex]; - if (at === n) { - marks[rowIndex][columnIndex] = true; - } - rowBingo &&= marks[rowIndex][columnIndex]; - columnBingos[columnIndex] &&= marks[rowIndex][columnIndex]; - } - if (rowBingo) { - result = true; - } - } - - return result || columnBingos.includes(true); -} - -function sumUnmarked(board: Board, marks: boolean[][]): number { - let result: number = 0; - for (let rowIndex in board) { - for (let columnIndex in board) { - if (!marks[rowIndex][columnIndex]) { - result += board[rowIndex][columnIndex]; - } - } - } - - return result; -} - -function playBingo(card: Board[], numbers: number[]): number { - // Prepare marks for each board - const boardMarks: boolean[][][] = []; - for (const board of card) { - const marks: boolean[][] = []; - for (let i = 0; i < board.length; i++) { - marks.push(new Array(board.length).fill(false)); - } - boardMarks.push(marks); - } - - // Process the numbers until we see a bingo in the last active board - const activeBoards = new Array(card.length).fill(true); - for (const n of numbers) { - console.log(`... ${n}`); - for (const boardIndex in card) { - if (!activeBoards[boardIndex]) { - continue; - } - const board = card[boardIndex]; - if (updateMarks(n, board, boardMarks[boardIndex])) { - // It's dead, Jim. - activeBoards[boardIndex] = false; - - if (!activeBoards.includes(true)) { - // Last one, yeah! - return n * sumUnmarked(board, boardMarks[boardIndex]); - } - } - //printBoard(board, boardMarks[boardIndex]); - } - } - - throw new Error('No more numbers, no winner!'); -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - return new Promise((resolve, reject) => { - const sequence: number[] = []; - const card: Board[] = []; - const pendingLines: string[] = []; - - rl.on('line', (line) => { - // Process `line` here - if (sequence.length === 0) { - sequence.push( - ...line - .trim() - .split(/,/) - .map((s) => parseInt(s, 10)) - ); - } else if (line) { - pendingLines.push(line); - } else if (pendingLines.length > 0) { - card.push(parseBoard(pendingLines.splice(0))); - } - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - if (pendingLines.length > 0) { - card.push(parseBoard(pendingLines.splice(0))); - } - const result = playBingo(card, sequence); - console.log(`Results for ${input}: ${result}`); - - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - '-example', - '', -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-5-example.input b/2021/day-5-example.input deleted file mode 100644 index 1d4e36d..0000000 --- a/2021/day-5-example.input +++ /dev/null @@ -1,10 +0,0 @@ -0,9 -> 5,9 -8,0 -> 0,8 -9,4 -> 3,4 -2,2 -> 2,1 -7,0 -> 7,4 -6,4 -> 2,0 -0,9 -> 2,9 -3,4 -> 1,4 -0,0 -> 8,8 -5,5 -> 8,2 \ No newline at end of file diff --git a/2021/day-5.input b/2021/day-5.input deleted file mode 100644 index 5baf6e7..0000000 --- a/2021/day-5.input +++ /dev/null @@ -1,500 +0,0 @@ -818,513 -> 818,849 -259,377 -> 259,599 -120,758 -> 977,758 -49,386 -> 170,386 -773,644 -> 773,745 -510,958 -> 797,671 -480,438 -> 14,904 -475,346 -> 648,173 -620,167 -> 477,310 -632,756 -> 275,756 -225,896 -> 432,896 -582,450 -> 93,450 -402,262 -> 254,410 -915,236 -> 709,236 -338,530 -> 338,375 -243,857 -> 370,984 -32,449 -> 32,26 -672,832 -> 203,363 -426,961 -> 426,402 -108,469 -> 550,27 -567,698 -> 495,770 -25,872 -> 861,36 -12,15 -> 960,963 -986,159 -> 986,765 -912,437 -> 714,437 -476,400 -> 476,873 -125,52 -> 951,878 -633,939 -> 633,641 -12,986 -> 987,11 -783,204 -> 467,520 -547,834 -> 413,700 -879,133 -> 879,890 -409,128 -> 365,128 -913,404 -> 913,598 -798,40 -> 841,40 -279,410 -> 279,758 -935,807 -> 959,783 -389,391 -> 389,38 -271,736 -> 271,865 -70,10 -> 814,10 -694,266 -> 694,92 -860,128 -> 860,966 -755,871 -> 608,871 -519,54 -> 519,833 -817,733 -> 156,72 -553,558 -> 726,558 -152,21 -> 830,699 -529,721 -> 608,721 -744,719 -> 744,221 -962,966 -> 10,14 -863,813 -> 863,984 -138,167 -> 801,830 -926,901 -> 926,769 -170,630 -> 623,177 -281,207 -> 510,207 -41,52 -> 945,956 -100,204 -> 100,43 -177,588 -> 469,588 -946,37 -> 201,782 -669,89 -> 669,868 -945,32 -> 46,931 -673,274 -> 412,274 -424,979 -> 169,979 -774,220 -> 774,571 -684,272 -> 229,272 -621,458 -> 621,884 -222,964 -> 222,608 -953,146 -> 145,954 -442,736 -> 442,230 -471,341 -> 471,124 -632,954 -> 968,954 -492,562 -> 911,981 -485,320 -> 485,349 -888,758 -> 888,23 -271,555 -> 732,555 -932,415 -> 792,275 -399,478 -> 399,472 -543,774 -> 543,261 -422,872 -> 422,715 -524,471 -> 445,471 -573,513 -> 573,762 -721,39 -> 482,39 -379,482 -> 379,479 -70,770 -> 336,770 -797,724 -> 797,364 -498,646 -> 498,410 -756,19 -> 756,83 -901,918 -> 11,918 -572,23 -> 362,23 -814,563 -> 750,627 -279,736 -> 249,706 -509,257 -> 509,897 -127,374 -> 399,102 -421,139 -> 607,139 -79,520 -> 166,607 -491,779 -> 284,986 -395,606 -> 395,164 -958,244 -> 442,760 -493,509 -> 673,509 -76,321 -> 482,727 -903,926 -> 103,126 -729,689 -> 63,23 -956,13 -> 198,771 -973,452 -> 193,452 -282,362 -> 896,976 -68,985 -> 985,68 -148,109 -> 310,109 -852,920 -> 371,439 -334,41 -> 864,571 -258,592 -> 72,778 -259,990 -> 259,308 -480,363 -> 480,751 -943,153 -> 801,153 -755,172 -> 123,804 -355,501 -> 437,501 -666,769 -> 340,769 -982,10 -> 23,969 -886,410 -> 886,669 -454,410 -> 454,218 -426,688 -> 227,688 -969,959 -> 207,959 -586,27 -> 591,22 -852,133 -> 166,819 -587,199 -> 781,199 -78,85 -> 78,394 -468,162 -> 727,162 -261,473 -> 573,473 -924,300 -> 924,873 -651,817 -> 651,600 -717,909 -> 717,187 -898,656 -> 454,656 -805,873 -> 507,873 -529,825 -> 529,217 -578,503 -> 783,503 -929,663 -> 920,663 -332,938 -> 332,381 -710,783 -> 272,783 -505,863 -> 240,863 -146,548 -> 146,849 -71,822 -> 820,73 -875,883 -> 451,883 -983,17 -> 30,970 -646,350 -> 646,330 -618,430 -> 881,430 -398,977 -> 643,732 -839,441 -> 406,874 -948,358 -> 178,358 -26,660 -> 26,612 -418,467 -> 418,115 -899,936 -> 899,611 -770,430 -> 770,648 -653,136 -> 95,694 -645,153 -> 818,153 -622,604 -> 77,59 -470,597 -> 592,719 -753,921 -> 743,921 -507,821 -> 507,275 -696,969 -> 433,969 -48,284 -> 552,284 -391,866 -> 187,866 -571,897 -> 107,433 -24,466 -> 24,186 -949,587 -> 582,587 -541,32 -> 541,583 -12,984 -> 986,10 -124,988 -> 124,904 -209,548 -> 209,12 -828,652 -> 34,652 -455,460 -> 905,910 -632,638 -> 343,638 -371,275 -> 145,275 -66,941 -> 945,62 -672,286 -> 672,301 -447,45 -> 82,410 -665,683 -> 487,683 -410,582 -> 670,842 -917,705 -> 917,323 -122,372 -> 403,653 -970,47 -> 40,977 -15,707 -> 732,707 -666,854 -> 666,256 -640,230 -> 188,230 -71,297 -> 71,472 -51,431 -> 339,431 -957,363 -> 82,363 -844,171 -> 274,171 -184,81 -> 184,786 -437,456 -> 138,456 -326,478 -> 814,966 -956,76 -> 226,806 -399,572 -> 399,877 -923,813 -> 923,898 -445,221 -> 947,723 -85,590 -> 415,590 -644,127 -> 644,140 -372,732 -> 372,522 -413,186 -> 244,186 -291,163 -> 197,69 -889,41 -> 208,722 -835,925 -> 835,616 -790,340 -> 426,340 -26,872 -> 805,93 -617,701 -> 828,701 -344,654 -> 530,654 -940,989 -> 41,90 -642,87 -> 206,523 -306,54 -> 306,761 -672,778 -> 672,868 -29,959 -> 974,14 -458,166 -> 86,166 -565,394 -> 352,181 -516,805 -> 457,805 -464,450 -> 756,450 -177,181 -> 661,181 -962,394 -> 630,62 -94,613 -> 12,613 -932,159 -> 818,273 -640,642 -> 976,642 -184,346 -> 184,22 -370,672 -> 458,672 -235,334 -> 770,869 -207,17 -> 811,17 -351,25 -> 896,25 -589,178 -> 921,510 -672,733 -> 937,733 -159,718 -> 787,90 -598,317 -> 598,455 -591,164 -> 591,374 -276,321 -> 515,321 -245,431 -> 245,350 -268,976 -> 939,305 -319,297 -> 823,297 -246,132 -> 229,132 -338,707 -> 338,59 -723,402 -> 723,739 -539,846 -> 94,846 -879,458 -> 783,458 -400,847 -> 770,477 -111,957 -> 858,210 -640,340 -> 878,578 -613,446 -> 115,446 -119,480 -> 119,425 -447,34 -> 986,34 -730,357 -> 532,555 -85,283 -> 26,283 -834,327 -> 263,898 -739,580 -> 640,481 -841,938 -> 841,123 -987,979 -> 23,15 -827,563 -> 632,563 -313,419 -> 466,572 -323,326 -> 455,326 -976,683 -> 976,314 -896,568 -> 338,568 -733,464 -> 819,464 -613,608 -> 493,608 -178,137 -> 178,663 -262,595 -> 262,308 -535,268 -> 851,268 -653,111 -> 653,723 -947,47 -> 23,971 -351,800 -> 351,806 -143,49 -> 850,756 -872,643 -> 872,265 -946,727 -> 427,727 -354,284 -> 938,868 -652,874 -> 652,447 -920,27 -> 387,27 -816,265 -> 816,366 -238,632 -> 336,534 -593,399 -> 593,425 -696,108 -> 138,666 -828,110 -> 240,698 -421,590 -> 847,590 -409,449 -> 622,449 -986,291 -> 45,291 -580,34 -> 663,34 -921,988 -> 35,102 -619,88 -> 249,88 -48,773 -> 503,773 -277,560 -> 377,460 -139,803 -> 123,787 -339,688 -> 907,120 -775,117 -> 775,203 -237,287 -> 507,557 -27,832 -> 429,430 -70,592 -> 672,592 -701,295 -> 69,295 -723,672 -> 714,672 -974,359 -> 292,359 -439,462 -> 439,973 -681,922 -> 357,922 -402,521 -> 25,521 -297,525 -> 297,227 -763,797 -> 763,153 -737,634 -> 869,634 -379,875 -> 810,875 -427,117 -> 705,117 -785,376 -> 265,896 -922,818 -> 141,37 -61,371 -> 61,432 -557,303 -> 411,303 -573,100 -> 295,100 -767,657 -> 231,657 -11,938 -> 875,74 -782,393 -> 782,502 -899,913 -> 519,533 -887,11 -> 244,654 -730,271 -> 426,271 -555,538 -> 379,538 -871,866 -> 871,461 -934,178 -> 934,845 -741,327 -> 325,327 -332,394 -> 518,580 -673,372 -> 809,236 -951,972 -> 77,98 -985,585 -> 985,55 -604,341 -> 269,676 -408,70 -> 455,23 -718,239 -> 718,522 -15,16 -> 984,985 -743,836 -> 852,836 -407,59 -> 246,220 -388,538 -> 388,587 -978,249 -> 810,249 -506,945 -> 506,644 -657,101 -> 657,522 -879,261 -> 935,261 -751,625 -> 926,800 -676,183 -> 573,286 -272,491 -> 765,984 -867,207 -> 570,207 -117,784 -> 750,784 -883,528 -> 883,845 -430,765 -> 581,614 -748,839 -> 748,775 -265,16 -> 188,93 -894,584 -> 525,215 -278,414 -> 19,673 -588,446 -> 588,656 -469,676 -> 469,354 -383,848 -> 669,848 -212,341 -> 367,341 -988,582 -> 988,825 -296,187 -> 785,187 -255,400 -> 255,286 -756,886 -> 524,654 -966,32 -> 966,940 -711,243 -> 81,873 -207,34 -> 359,186 -555,850 -> 45,850 -41,962 -> 947,56 -15,888 -> 15,795 -773,709 -> 579,515 -228,517 -> 228,334 -495,290 -> 965,290 -462,309 -> 462,421 -945,274 -> 945,735 -547,361 -> 547,140 -37,930 -> 836,930 -987,445 -> 45,445 -25,766 -> 757,34 -643,946 -> 318,621 -507,402 -> 507,981 -22,903 -> 488,437 -887,487 -> 957,487 -57,434 -> 21,398 -688,907 -> 917,678 -146,498 -> 146,965 -375,939 -> 888,426 -966,151 -> 684,433 -160,373 -> 722,373 -410,571 -> 410,683 -588,667 -> 588,337 -832,348 -> 376,804 -567,430 -> 453,430 -368,442 -> 97,442 -11,191 -> 584,764 -647,965 -> 647,331 -576,856 -> 976,456 -205,287 -> 205,495 -677,872 -> 677,246 -21,16 -> 973,968 -949,738 -> 126,738 -921,595 -> 921,370 -539,821 -> 660,821 -143,188 -> 143,793 -639,930 -> 639,454 -522,360 -> 917,755 -128,281 -> 647,800 -456,365 -> 456,34 -434,530 -> 431,530 -549,792 -> 549,892 -414,229 -> 41,602 -289,468 -> 592,771 -555,624 -> 727,452 -187,780 -> 187,838 -807,282 -> 807,968 -52,249 -> 52,332 -797,525 -> 462,190 -295,562 -> 654,921 -862,627 -> 252,627 -22,116 -> 866,960 -155,652 -> 155,979 -598,748 -> 51,748 -130,601 -> 231,601 -468,183 -> 468,414 -208,193 -> 927,912 -25,755 -> 770,755 -667,755 -> 916,506 -395,103 -> 395,468 -763,62 -> 763,153 -371,816 -> 371,109 -508,138 -> 37,609 -464,983 -> 707,983 -282,295 -> 282,536 -646,680 -> 646,775 -95,117 -> 95,62 -606,963 -> 203,963 -403,195 -> 97,195 -743,293 -> 743,815 -243,748 -> 431,748 -953,54 -> 22,985 -693,810 -> 656,810 -163,221 -> 728,786 -187,648 -> 187,337 -98,559 -> 98,165 -903,49 -> 46,906 -600,779 -> 432,779 -500,606 -> 500,878 -812,797 -> 31,16 -204,786 -> 517,786 -952,757 -> 952,923 -66,809 -> 66,831 -479,72 -> 17,72 -96,430 -> 96,932 -346,667 -> 796,667 -731,102 -> 162,102 -755,846 -> 755,135 -90,18 -> 404,18 -828,802 -> 134,108 -278,946 -> 278,765 -289,163 -> 869,743 -134,58 -> 887,58 -354,735 -> 904,185 -897,74 -> 897,716 -508,904 -> 508,719 -285,358 -> 795,868 -51,155 -> 51,643 -579,388 -> 431,240 -79,330 -> 869,330 -955,863 -> 140,48 -800,473 -> 689,473 -711,128 -> 918,128 -787,166 -> 787,36 -257,684 -> 873,68 -984,986 -> 10,12 -76,580 -> 660,580 -265,868 -> 955,868 -569,491 -> 466,594 -535,654 -> 37,654 -889,751 -> 411,273 -681,491 -> 600,491 -459,721 -> 459,109 -824,130 -> 689,265 -406,780 -> 406,965 -18,31 -> 904,917 -179,91 -> 232,38 -280,552 -> 428,700 -967,980 -> 19,32 -47,289 -> 738,980 -160,592 -> 120,592 -710,412 -> 28,412 -40,430 -> 747,430 -435,821 -> 747,509 -36,741 -> 36,363 -787,30 -> 847,30 -725,968 -> 725,940 -739,356 -> 27,356 -65,193 -> 419,193 -318,513 -> 404,513 -150,230 -> 150,968 -847,410 -> 847,505 -950,188 -> 950,278 -816,312 -> 587,541 -980,145 -> 154,145 -79,781 -> 616,781 -433,284 -> 433,309 -624,264 -> 569,264 -604,859 -> 570,825 -936,691 -> 350,105 -259,631 -> 648,242 -445,27 -> 445,872 -438,689 -> 977,150 -718,603 -> 718,327 -967,310 -> 98,310 -439,381 -> 439,35 -645,240 -> 282,240 -475,54 -> 475,658 -972,610 -> 759,823 \ No newline at end of file diff --git a/2021/day-5.ts b/2021/day-5.ts deleted file mode 100644 index 6ac52b2..0000000 --- a/2021/day-5.ts +++ /dev/null @@ -1,136 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -type Point = { x: number; y: number }; -type LineSegment = { start: Point; end: Point }; -/** - * Index is y*MAX_X+x, mapped value is number of line segments at that point - */ -type Floor = Map; -interface FloorOptions { - maxX: number; - maxY: number; -} - -function parsePoint(s: string): Point { - const [x, y] = s - .trim() - .split(/,/) - .map((v) => parseInt(v, 10)); - return { x, y }; -} - -function parseLineSegment(line: string): LineSegment { - const [p1, p2] = line.split(/\s*->\s*/); - return { - start: parsePoint(p1), - end: parsePoint(p2), - }; -} - -function toString({ x, y }: Point): string { - return `${x},${y}`; -} - -function printFloor(floor: Floor, { maxX, maxY }: FloorOptions): void { - for (let y = 0; y < maxY; y++) { - let line = ''; - for (let x = 0; x < maxX; x++) { - const v = floor.get(y * maxX + x); - line += String(v ?? '.'); - } - console.log(line); - } -} - -function updateFloor( - floor: Floor, - { start, end }: LineSegment, - { maxX, maxY }: FloorOptions -): boolean { - // Find the index delta between the two points, and then update the floor - // at all points touched by the line. - // For the first part we can only accept a line segment where the delta is - // +/-1 (horizontal) or +/- MAX_X (vertical) - const deltaX = end.x - start.x; - const deltaY = end.y - start.y; - console.debug( - `Applying line segment ${toString(start)} -> ${toString(end)}` - ); - - // "Draw" the line - const startIndex = start.y * maxX + start.x; - const endIndex = end.y * maxX + end.x; - const deltaIndex = - (deltaY < 0 ? -maxX : deltaY > 0 ? maxX : 0) + - (deltaX < 0 ? -1 : deltaX > 0 ? 1 : 0); - let index = startIndex; - do { - floor.set(index, (floor.get(index) ?? 0) + 1); - if (index === endIndex) { - break; - } - index += deltaIndex; - } while (true); - return true; -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - const opts: FloorOptions = input.includes('example') - ? { maxX: 10, maxY: 10 } - : { maxX: 1000, maxY: 1000 }; - return new Promise((resolve, reject) => { - const floor: Floor = new Map(); - rl.on('line', (line) => { - const lineSegment = parseLineSegment(line); - if (updateFloor(floor, lineSegment, opts)) { - if (input.includes('example')) { - printFloor(floor, opts); - } - } - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - const overlappingPoints = Array.from(floor.values()).reduce( - (s, v) => (v > 1 ? s + 1 : s), - 0 - ); - console.log(`Results for ${input}: ${overlappingPoints}`); - - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - '-example', - '', -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-6-example.input b/2021/day-6-example.input deleted file mode 100644 index a7af2b1..0000000 --- a/2021/day-6-example.input +++ /dev/null @@ -1 +0,0 @@ -3,4,3,1,2 \ No newline at end of file diff --git a/2021/day-6.input b/2021/day-6.input deleted file mode 100644 index b702e60..0000000 --- a/2021/day-6.input +++ /dev/null @@ -1 +0,0 @@ -1,2,1,3,2,1,1,5,1,4,1,2,1,4,3,3,5,1,1,3,5,3,4,5,5,4,3,1,1,4,3,1,5,2,5,2,4,1,1,1,1,1,1,1,4,1,4,4,4,1,4,4,1,4,2,1,1,1,1,3,5,4,3,3,5,4,1,3,1,1,2,1,1,1,4,1,2,5,2,3,1,1,1,2,1,5,1,1,1,4,4,4,1,5,1,2,3,2,2,2,1,1,4,3,1,4,4,2,1,1,5,1,1,1,3,1,2,1,1,1,1,4,5,5,2,3,4,2,1,1,1,2,1,1,5,5,3,5,4,3,1,3,1,1,5,1,1,4,2,1,3,1,1,4,3,1,5,1,1,3,4,2,2,1,1,2,1,1,2,1,3,2,3,1,4,5,1,1,4,3,3,1,1,2,2,1,5,2,1,3,4,5,4,5,5,4,3,1,5,1,1,1,4,4,3,2,5,2,1,4,3,5,1,3,5,1,3,3,1,1,1,2,5,3,1,1,3,1,1,1,2,1,5,1,5,1,3,1,1,5,4,3,3,2,2,1,1,3,4,1,1,1,1,4,1,3,1,5,1,1,3,1,1,1,1,2,2,4,4,4,1,2,5,5,2,2,4,1,1,4,2,1,1,5,1,5,3,5,4,5,3,1,1,1,2,3,1,2,1,1 \ No newline at end of file diff --git a/2021/day-6.ts b/2021/day-6.ts deleted file mode 100644 index 6a59c11..0000000 --- a/2021/day-6.ts +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -/** - * Simulate the fish "naively" - * - * @param ages - * @param days - * @returns - */ -function simulateBruteForce(ages: number[], days: number): number { - let state = ages; - for (let i = 0; i < days; i++) { - state = state.reduce((r, age) => { - if (age === 0) { - // Produce new fish - r.push(6); - r.push(8); - } else { - // Count down - r.push(age - 1); - } - return r; - }, [] as number[]); - } - return state.length; -} - -/** - * Simulate the fish using age buckets - * - * @param ages - * @param days - */ -function simulateWithBuckets(ages: number[], days: number): number { - /** Age buckets: Number of fish per age group */ - const buckets: number[] = ages.reduce((r, age) => { - r[age]++; - return r; - }, new Array(9).fill(0)); - - for (let i = 0; i < days; i++) { - // Shift the array left, and create new fish for the number of fish - // on age 0 - const [newParents] = buckets.splice(0, 1); - // Parents start back at 6 - buckets[6] += newParents; - // ... and the newly spawned fish pop up at the end (which we just shifted away, so we - // just need to push that back there). - buckets.push(newParents); - } - - // Add up all the counts to come to the number of fish - return buckets.reduce((r, count) => r + count, 0); -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - /** Ages of all fish ("state") */ - let ages: number[]; - - return new Promise((resolve, reject) => { - rl.on('line', line => { - ages = line.split(/,/).map((v) => parseInt(v, 10)); - }); - rl.on('error', err => { - reject(err); - }); - rl.on('close', () => { - // XXX: Use both functions to not get complaints about unused code - const fishAtEndPart1 = simulateBruteForce(ages, 80); - const fishAtEndPart2 = simulateWithBuckets(ages, 256); - console.log(`Results for ${input}: ${fishAtEndPart1} fish after 80 days, ${fishAtEndPart2} after 256 days`); - - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - '-example', - '', -]; - -main(INPUT_SPECS.map(inputSpec => `${basename(process.argv[1], extname(process.argv[1]))}${inputSpec}.input`)).catch(err => console.error(err)); diff --git a/2021/day-7-example.input b/2021/day-7-example.input deleted file mode 100644 index 18bd32a..0000000 --- a/2021/day-7-example.input +++ /dev/null @@ -1 +0,0 @@ -16,1,2,0,4,2,7,1,2,14 diff --git a/2021/day-7.input b/2021/day-7.input deleted file mode 100644 index 822b016..0000000 --- a/2021/day-7.input +++ /dev/null @@ -1 +0,0 @@ -1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,315,1081,464,841,82,86,483,2,1163,1189,184,369,510,519,13,0,1127,899,1157,1018,3,1014,507,330,20,4,374,641,1768,773,1130,827,1132,166,217,3,460,51,767,484,109,48,143,977,790,1139,426,50,391,537,1140,478,41,1560,1457,180,814,138,338,751,1164,1088,157,1168,163,880,1477,1236,496,446,582,215,840,19,6,626,84,473,977,191,281,1166,230,643,772,985,65,290,389,409,366,1339,499,4,20,262,58,1294,1043,1625,77,284,415,220,583,110,70,639,424,273,28,669,920,1580,434,377,24,446,113,100,1040,1271,874,73,629,87,88,877,959,896,1478,377,14,409,1150,975,547,181,367,549,941,923,1175,19,293,91,1079,495,8,156,807,1423,337,544,505,694,45,968,349,472,1333,43,1339,139,383,676,105,81,0,208,397,628,1033,429,1642,1635,397,675,273,263,165,965,600,571,834,13,411,592,2,49,1706,1288,241,115,5,1046,1301,688,474,34,817,200,410,233,181,173,8,124,527,1266,238,33,482,1066,1074,381,197,139,828,45,843,133,823,265,685,463,680,958,561,101,258,339,7,578,38,176,1127,57,147,186,795,685,769,27,547,1089,252,125,1182,63,907,1300,1022,1040,613,1082,964,693,7,130,259,75,5,1172,1380,362,1203,1936,666,50,600,482,497,106,724,153,52,480,848,1216,814,156,730,20,831,441,160,81,4,750,81,537,1006,320,493,526,63,112,0,467,65,50,1228,105,121,1123,568,232,6,946,436,429,1116,309,13,1471,60,15,1143,385,34,374,140,413,24,593,97,7,127,504,221,1380,585,661,326,709,91,1323,722,256,346,43,296,5,477,356,182,476,1109,107,1137,151,1303,201,796,760,1144,51,410,694,68,49,78,32,24,781,1347,34,16,137,999,47,94,788,409,188,853,362,862,576,386,621,52,341,908,362,160,1373,1118,368,222,125,389,327,168,136,197,445,206,564,517,95,547,765,526,584,1115,150,674,312,246,33,168,266,92,535,23,442,518,145,358,531,150,174,545,1525,576,1721,5,1369,1112,787,9,1266,955,265,385,823,1129,62,1045,1682,4,157,268,449,77,340,12,401,818,28,722,232,116,41,1250,504,1448,108,748,161,42,634,975,1046,50,371,474,669,271,910,263,1091,566,35,181,29,163,652,497,1108,878,448,44,241,319,585,530,176,596,1334,2,181,63,807,53,738,851,952,502,127,983,59,0,22,1143,393,75,292,105,592,649,1709,1505,0,1,634,1815,1505,23,145,117,1286,1641,372,273,348,688,113,0,823,1829,607,89,110,30,667,997,987,354,804,766,243,211,783,76,152,401,667,477,555,280,504,252,287,448,495,59,83,353,219,112,198,174,1496,3,803,765,1166,446,1062,451,1365,778,115,381,102,3,209,236,8,87,169,145,139,1032,1702,176,525,436,73,5,35,1512,198,370,70,358,135,46,153,473,48,521,315,709,473,136,363,60,256,1048,81,1037,59,456,343,18,935,51,1329,1624,1134,189,526,578,190,1635,396,211,583,83,165,89,1073,1251,241,607,833,105,183,300,998,1849,1127,734,325,767,215,1375,326,300,228,246,1221,204,40,718,26,231,31,608,453,11,169,104,380,339,281,23,778,1023,385,251,972,47,101,779,122,471,1003,45,261,1223,493,48,92,948,1269,519,319,720,3,145,1509,24,65,219,25,687,781,465,38,554,244,99,335,55,817,13,1009,319,112,93,537,454,298,393,1217,941,673,356,142,213,140,422,11,1050,143,270,21,58,145,188,486,821,942,1,420,844,451,45,560,701,758,624,149,267,63,286,236,339,120,1145,747,1835,471,540,684,1549,204,285,0,335,387,729,81,17,162,24,25,212,64,1051,373,629,187,34,228,562,362,25,16,475,114,1092,736,1014,896,91,1516,93,210,12,432,88,411,353,638,480,418,1087,45,818,9,606,568,286,507,139,1281,1709,228,510,218,484,498,559,948,88,207,968,84,142,364,44,15,542,133,363,299,753,212,313,277,589,628,821,1481,2,59,18,125,644,324,38,704,559,387,72,36,15,231,647,57,202,1140,311,1125,538,611,192,459,1,598,310,211,406,1868,624,1126,373,369,202,373,1309,903,554,202,259,1174,254,436,997,39,513,811,28,948,434,428,426,419,167,320,748,145,447,735,1128,440,232,211,481,332,591,4,325,875,45,834,269,527,361,603,488,1071,166,1734,326,241,1434,899,738,225,240,1407,6,1197,743,850,25,136,241 diff --git a/2021/day-7.ts b/2021/day-7.ts deleted file mode 100644 index ce94666..0000000 --- a/2021/day-7.ts +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -function linearCost(positionDelta: number): number { - return positionDelta; -} - -function increasingCost(positionDelta: number): number { - let cost = 0; - let nextStepCost = 1; - for (let position = 0; position < positionDelta; position++) { - cost += nextStepCost; - nextStepCost++; - } - return cost; -} - -function alignCrabs( - positions: number[], - calculateCosts: (positionDelta: number) => number -): number { - // Brute-force and find the position that takes the least amount of - // fuel. - const maxPosition = positions.reduce((max, p) => Math.max(max, p), 0); - let lowestCost = Number.POSITIVE_INFINITY; - position: for (let candidate = 0; candidate < maxPosition; candidate++) { - let cost = 0; - for (let crab = 0; crab < positions.length; crab++) { - cost += calculateCosts(Math.abs(candidate - positions[crab])); - if (cost > lowestCost) { - continue position; - } - } - lowestCost = cost; - } - - return lowestCost; -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - return new Promise((resolve, reject) => { - let positions: number[]; - - rl.on('line', (line) => { - positions = line.split(/,/).map((s) => parseInt(s, 10)); - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - console.log( - `Results for ${input}: linear ${alignCrabs( - positions, - linearCost - )}, increasing ${alignCrabs(positions, increasingCost)}` - ); - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - '-example', - '', -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-8-example.input b/2021/day-8-example.input deleted file mode 100644 index c9f629b..0000000 --- a/2021/day-8-example.input +++ /dev/null @@ -1,10 +0,0 @@ -be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe -edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc -fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg -fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb -aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea -fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb -dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe -bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef -egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb -gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce diff --git a/2021/day-8.input b/2021/day-8.input deleted file mode 100644 index fd3d8ec..0000000 --- a/2021/day-8.input +++ /dev/null @@ -1,200 +0,0 @@ -caebgd dagc eabgd aebfgc fbdacge edg dg dbgcef eabfd cgeba | gbcdae dagc acgd gd -fgcbed bcedga cafb acgfd cgabd cgf dfaeg dfbcga bceagdf fc | cf gdfea fdagbc dfacg -gaed egcbdf edagcf fcaegdb facge afg ga ecbaf fgced fgdabc | cgeaf gfa ga efbac -cbdeg cbgeadf cgdfa cgdbae decgf efg cebf egbfdc fgbead ef | fge gfe dcegabf gdcfe -bacd cgdbe ecgbf cd cde degba cfaegd gfadbe gbdace baegcdf | cfgdea dce bacd cabd -gdbafc cedagb cebga bc edcb gbdefa cebgdaf agfce acb bgdae | afgedb bdce dabeg dbec -fadce bad edafbc cgbfa edcagf dacbge dfabc bgecadf edbf bd | efbd baegdc dab db -fcaed eb afcdge cfbae gacbf edab becgdaf gcedbf efb bdecaf | be gadbfec eb cedfa -cdgbea ebcga feacb age ge afcdgb faegdc acbgd agcfdbe bdeg | gedcab dcagb gea edbg -eda bgeaf eabdcg ad ebgdacf egdfac ecdbfg dcfge acdf dagfe | ad ad da beagf -cegfa bf ecfabd fgcb egcafd ebfga bgade afb eagbfc dgfbeca | bcegaf fcgb adgbe bcgf -fegacb dbagc gdcae fbcd bc dfbgca gdbfa cgb adefbg ecdabgf | cgb fbgdac cabfdg acdeg -gfbead cfbgea cfeb bf agcfb baf cdgaf begacd aebcg acgdfbe | fab gdcbeaf afcbeg bfa -df acgbf bedag gecbdf dgefacb fdagb gfadeb fbd abgecd efad | bcafg cafdgeb bdf fd -defbc dg gadc caebdfg bceagf gecba adegbf ebagdc gecdb dbg | bfgdea aefbdcg dgb dbceg -cegbd cafegb gedcab gcebdf ecdf dfbag fbgde ef efg fbaecgd | fedc ef fdec ebagcf -dbfag gabdcf dfgbeac efdcag gbcfe ed efbadg efd bade efbgd | bagfd def ed efgbda -gafbcde gfbdc fc geafbc cgf ecdfgb cfde dbgac gdfeb gedabf | fced gfc cdbag gfc -ef adbefg efdbc cfabd fcea fbe cebdg cbfgda abecfd dagbefc | degcbaf ef fecdagb dafebc -acdbf abefgd ea dgcfe acedgf agec faedcgb afe gcbdfe fecad | geca gebadfc fgeabcd efdca -agfecd acbg aefdb bg gdcfa gdafb cebdagf gfb dgcafb cgbefd | fbg dgafc fbg bafdg -db ebafd dcafeg bcedag eafgb bcdf ecafd adb eabdfc cdbgaef | bgafe dfbea bd daefc -egfacd cegfa afbdg facgbe de dfegbc cdae edafg egd ecdfbga | edg defcga aegfc de -abdgfce begca egcbf ag gdafbc afge fbdcge daecb cefabg cag | gbfced ga cgedbfa ag -faed abcedf eafdbcg aebcf cbagf cgebda ef fbe cbgfde bdcae | afbcg dafe fbe fbe -bcea cfdae dcafeb ab cfbdg dgeabf afbcd baf fdacge gacfdbe | baf decgfab fab abce -dbeacg agefcd agbefdc cagfe ae aeg aedf gdafc bfceg bacdfg | gea begcf fdcage ea -cagdeb ca bcfgad badgef cbaf cgbefad adc fcdga gdfec bfagd | aecbdfg afcb ac bcfa -bc begda gebfcad bfcd dbeac abdfce dcafe cbe cafdge bgcfae | bcdf ebdga gbfecda bce -dfacgb edbcg gfedab egfab bac begac fcea ca dgfcabe ebacfg | bac cba bgcde ca -fgacbe dgeba agebf afb fbcaed eafcgd fb dfegacb bgfc cfgea | cfegabd ceafg bf cbadef -fgcab ceabdgf fdabc da gdabcf gdcaeb ecfbag fadg cdbef acd | fagd gfad fcbgae adgf -afbgecd cedga cdfb ebgdcf gbfade bcfeag cedgb efgbc bd gdb | fedbcg cefdbg edcag dgb -bfcga gfadb egcadf cbeagfd bdfeag bcfegd bd edgaf dbae dfb | bfgadec dfb bfd cbfga -cbegad bacde eafdb bcgea cad cfgadb cd gced fgedcab bfecag | fdgbeac eacbdfg acdbe abdfe -cebaf dcegbaf edfgab cabgfe bafeg cgaf aegbdc cea febdc ca | ac ac ca cfga -db bfd ecdfg febdc debfac egdfab cadb efgacb defacgb bcfae | edbcagf bd debfac fdb -egfdcab dcgbe dacgef fbad bafcge ab degfa ebfgad gbdea gab | ba fabgecd ab agedbf -afbc efadc efcgabd dfbeac ac bdgeac cfgbed afgde cfdbe dac | ac fegcdb afedc facb -acbde cgfdea cdbge cfbdea abd ab gacbdfe fdcgab acefd fabe | fbae dagefbc aefbcgd dba -cedbfga dabecf afbge fab ecbfdg gedfba fbgde cbeag dfag af | beafg acbfed fa gdaf -ecbgfa eab agdfebc adbg gdfbe dfgecb dabfe afced bagfde ab | bdag gdba dfbge gbda -egfdac eadbg gfdab bcdega ae egabdfc cdfbeg dae gcbed bace | dgbefc gadefc ea eacb -bgacf dgfcea cbfgeda fdab fa fag fbgadc gcbef cdabeg bcgda | gfa fag afg aedcbg -egafdcb dcega dgfbc egdbaf ebdcg dbe eb cabdeg ceab fcdaeg | bed edcfag gadefc fcdbg -dgcab afgb bcg dcaeb dbgcaf bg ecfdgba gafced fbcdeg cfdga | cefgdb gacfbed afdgc gbcdfa -cgeda bafcg cgdfa dgfcae bceagd bdgface adf fd feabcd efdg | edfg gdeca cgbdfae dcfgaeb -dbefga eadcgb gbaedcf daebc geadc bd bcgd bafec bad gaecfd | edagc abcef fceba aecdg -bcegf cfbega bgedca befca gabecdf bgc gfca gebdf cg dcfabe | efdbg bcg acgf fecbadg -gfcdeba dbaec ecgaf gde agedfb bcafeg gdfc dgeac dg cadefg | egfca fegac edg daebgf -bea geadbf be efcad afecgb adfcbg cbefa fcabg gecb egbdfca | eab cbfae gbcafed cbeadgf -adgfec bgea fbcdg be fdceba bgedc edb acged bfdceag dgbcea | decfba efcdba gbdface aedgfc -ebgfc dcb dc ecfd fecbgd debcg bgfacd defcgab bacgef dgabe | dc adfbceg befgc cfed -cbgdea gafc fcegd eagdfb bfdce egc efdag gdafec cg gfbceda | cg ceg dgfea cg -fgdab egacbfd decgaf eaf edcfgb ea efdcb aefcbd eadbf abec | fdbea ea acefdb ea -bdegcf aegfb eacd ec acfgd gfdeca fce adcfbg begafdc gcaef | acde gbefcd adce fec -cdgfbe fdacg cegdf cebd cbeafdg efgcb aegcbf bgfead efd de | fcegdba cbde gbcadfe fed -adfge efgbda gacfde gecfba ce feacd adbfc cgde fce dfabgce | fgcaed cgde gfaced fdeac -ga cgaefdb dcebfg fbegac gbda acdef cdgeb gbaedc ecadg cag | bagd bgfdce cbgde dbfaecg -gec efdabg bfgdcae dfebc agbc aefbg afgbce agecfd cg cegbf | acfdgbe cbdef abcg afbedcg -ebcgaf cagdf afbdeg fbcda dcfbeag beacfd befca bfd bd cebd | dfb dbf feacbg gfdaecb -ecgdfa afe gbafd bfgdac ae decbf dgebaf afbed abeg cedabfg | egab cgeabfd eadgbfc ebag -agcfdeb fdabe gfcaeb edf cegfad badce gdbf fd gbafe fedbga | efd bfgd daecgfb cabefg -bcdef gefcadb fdeba fdega ba bgea bgdafc efbagd dfcgae dba | ba ba edafb ebga -acgbe age ga agebfd afcebg bdegc acfeb fgca cefdba cabegdf | ag eag afgc ag -bacfd feb gfea dabge fegadbc adegbf fe aefdb cbdgae gdcbfe | ef ebdfcg fgdeba efb -efgca fadbc daecgf ecbfgd gd daeg dfcagbe agfdc bafecg dgf | fgd cfeagb afegc dfg -cgeabd cdagf dfab afcbgd dceafbg adgbc cfd df efdgcb afgec | cdf cfabdg abfd df -bgacef acegf adgce cgbfaed dgbec gcdefa afed ad badcgf cda | ad egadc degbfac efcagd -de ceafb bfedacg decf cbeda aed gdefab dfacbe gadcb gecbfa | acefb eda edcf ead -fdebga dgbcef baf af caefb debcf baecg cgdfaeb dafc facdbe | af fdac fgceadb efcba -dgbfac cabdefg ag gda dgcbf gafdb dfaeb bedgcf cafg adcebg | fgadb egfbcad fgca gfbda -egcbfda fagbde cb egbcf fbc dcgb cdbafe fgdbe dcefbg ceafg | bfc gfcebda bcf bcf -cfeba ag fecag feacgb eag defgc egabfd gbcafed agcb bdacef | gcfabe efcadgb ga gabc -fgeadb gbfdace feacb ed bacfde fdbcg edca ecbdf cebgfa def | ebcfa acebdgf efd aced -fcgad aegfdb ea bdfcea dea egfbd aebg cgbedaf begfdc fedag | geba egbfd fdagbe dcbaef -faebdg efbca fadce bgefa fcbgae dbecfag bgcf cb ecb dgaecb | cadebgf ecb gcfb cb -ecdf begca cbagfd ed edb dfebacg cdgfb bcedg cgbfed edagbf | de dfce gedcbf de -badfec dfgcab gdbeafc cbf defc acefb ebdgaf cf abedf egacb | cdfe cdef fedc fc -afcgbd fdcg fbc bgdac acbgef cf fcabd gdebca fbaed fcdageb | cf fbc cf gfcd -cefba dbef fe gdafec dbcae fdebac bfadcge fec gceabd abcfg | gacedb debac bcaed gacfdbe -bagfe db bdf gafdc bfgda cgefbd cafedg fcgabd fdeacbg dacb | gabdf cdgbfa bd egfbdc -dbcaef bacfd begfcd gbafc cedbf da eabd gecdfa cda fbecgda | aedb cda efcdb adcfbe -faebgd afcbdg gf dbacfeg gdf degfa dcfea gebda dgaceb gfbe | bgfe decaf gf edgfa -fg aecgbfd ebcfa efabg adgeb fge egcbdf bedagf dbcaeg fagd | fg dfga gfda gafd -cedgabf dcba ab cedaf bae cabefd fgaced fdaeb fabgec dfgeb | bedfac ab fecbga debfcag -dec ce fcabde daefb fgabde aefc bdagc dcgfeb efcdabg caedb | gadbfec ecfa baefgd ce -egcaf ed adbe afbcd dgfecba acbdgf edf decfab edcaf egbcfd | dgecfab eabdfcg fbdaec abed -fea febcg eacgf ecda cdgfa agcedfb edgfba ae agcfde cbadgf | fcegb fgbaced dcafg caed -gebfd ec dec eabc bafcged debgc fecgda fdgabc dcgabe cgadb | adegbcf gbacfed bfgcdea ce -egfdab cad bcgad cd bcfga gfdbcea dgcaeb cedg defbac beagd | cadbfe decg cd cadfeb -cge gadebfc fbcgae gc dagec agdeb dcefga cgdf afbecd ecfda | ebgcaf dbeag fgcdbae dgcf -bdegca ecbdaf bfae cgdfb ebafdgc ba dfabc bac feagcd fdcea | bac ebcfadg ba ab -gceda eab agbfedc eafcdg ab gbac bgdef gacbed dgbea cfaebd | bgfcade ba abgc bae -gbfe eg gcfdeb daebcg bcdef cgefd cdfag fbdeac egcadfb gec | ge befgdc gce egc -bga gbeacd cbgde gdefcab cagbdf ab beda cfbegd aecgf agecb | agfce daeb bead agb -fedgba agecbf bc bcdf cgb febdcg ecgfabd gcade dgbec efgdb | bgedfac cb bc bc -gfaeb bcdfe cea gfca bdacge aecbdfg fegbca ac dfgbae caefb | cfga agcf cfga cbgade -cgeab fbegda adb dagbfec eafgbc bd bgcd adecf cegdba daebc | efbcdag gdcb bd deacfgb -bcagd cbgde gbfad eabdgf cda ceabfd fcag cdgabf agcbdfe ca | ca ca ac cda -agdce dageb eacdbf ecgdaf bafgd dgfacbe dgbaec bceg bea be | gceb bgdcaef edgac aedgc -bceadf adcfeg ga dfag geacd cabegdf ceafgb gca aecfd edcbg | ag acbfde gdfa ag -fdcegb abdfce cdega bgcad gfea cae ae bcafged fagedc fgdec | gfdce bafcde gfcdeb ae -egbcda cebadf bfe ef bedcg bgfda fgec fedbg begcfad gdbcef | bef gcbeda ef ecgf -egfdb cgd gdbfea cgbdf fdcba fgbdaec agbdec cg fecg cgdbfe | abgfedc fbcgd cegf gc -cfbegd ab gbacfd agefd ceab baf acfgdeb eafbgc bfegc bagef | ba abf beca baf -fcega fecda cbgaef fgaedb gbfc geadbc fag ecbdgaf eacgb fg | ecdfa bfgc dgebaf gcabe -aefdcg gfdcab ab fagb dbaegcf adb faecbd gcadb fcgad ebdgc | gadcef bfdaecg fgba fgecad -eabfc cdebf bgfca ecfbgad fbdceg aeb gceabd afde ea cbfade | abcdgef eabfc abe bdcfae -cd dgfceab dec cbegfd gedaf adfgec ecbag fgadbe cadf cgdea | fgedbc edc dce adcgfeb -agcdbf ecdgf adfcg agfcbed ef ecdfab efc agfe cgebd defagc | eadcfb cfdbega cef geaf -cdbafe deacf ga dbecag fecdagb bcfge gfda caedfg gae eagfc | ga eag gfcebad cfgae -ceadfg bdf gfbec adbe fbegd abgdfc bd gdefa gdfeba dgacefb | bagedfc facedgb fbd bd -ecdba ecdagb gcfeda fbdaeg cfedb befcdag ca agedb abcg ace | cea fbaged eca bcag -gfedc gdaf gaefc dcf bgcde gdeafc fcgadeb gecabf cdafbe df | fd gcaef df egfdca -afegb cefgb eadcbg cgfbad dbecg cfde aegbcdf fcb gdebfc fc | fbcged bcf gbced aefgdcb -ca bfeda cae ecdfgb edgcf dgceaf gbaced afcg gbeacdf aefcd | ac dfcebag cagf ace -begcad efdagb fbgeadc fedcba aec abedg fcegb ca cgda abegc | abcfgde fgebadc bagedf gdca -aegb cfeadb acdgf decgbf ecgdb gcfedab bgdcea ba gbdac bad | bgceda gdafc fgadc dafcbe -fgecba aec adfe deacb ae abegdcf bcdag ecbfd gecdbf dafceb | gdcab ae edfa daef -agfde eacg adebfg fdgcb cafdg fgdeca cfbaed ac gcadfbe acf | fca gdfae acge dbeacf -fbagce de deg edfa fcbdg gbdcae aegfb dbgfe dgacbfe gefbad | edfa de ged bdgcf -bacfdg cdeafgb aecbfd daefb agedc afc abdefg cebf deacf cf | gbdafc efbc cfead fc -cegfab cdag bdc dc febad gfdbce dcaefbg gfbac dcafbg cdabf | dgafcb cdag dcbgeaf gaefdbc -dagefb acefg afdcb gd dgfaecb facbgd bcdg gda badcfe fgacd | fbecgda cfadb gbdc fcaeg -gfbd cfeda gabcfe db dba baefg beafd bcgdae fedcbag efbdag | dba bad ebgaf dbegfca -cf fbdega aefbg afbcedg edgca dgbcfe gfaec febcag ecf afcb | aefbg gcaefb dbcegaf cef -gebdaf abgd cdabfe gacefbd agfed dg ged fegac aebfd fbdcge | egd abdegcf gadb afbgde -gcdf efdcb acfebd beagdc gd bdefg ebfcgd bdg fbega geabcfd | dgceba ecadgb adgfbce edbgf -fdcaebg efbdgc bgdacf dcae cbdge gebaf abd edgab da bgaedc | cebagd ad da gebcda -bfgcae cbd bcfea aedcb gbefcd cd adecfb adfc cagdfbe dbega | fcad cdabgfe dacf dcb -becg gfbace egacfbd acbfg acdfgb aec ce bdfea cgedaf fbcea | afcbg fedagc befac aecfgd -befa cgfed cfadb gdcfba acdfe ace edgbac fgcdbea ceafdb ae | feab eacdf bcdgafe bfae -bcdefag dafeg fgec dgeafc gea gdfbca cgdaeb bfdea eg dgafc | eg aefcdgb ecdfag gea -gfadb gedfb bdecgfa adbefg dcgaf abf gdcefb aebg ab bafced | gdbfe gbfed ebag cabgfde -dbegfa acgbdf eg gcfbed gdafb bfacegd ebg aged fageb bacfe | ge gefcdba ge bgdfa -adbgec fdceg afdgc bedf cfe fe gaecbdf faebgc gcbed fcbedg | acfdg gdeabc debf ef -dfgbe da ecbadg dafeg fadb gfdbea dagcfbe dbgfec cfgea dga | befdg agd eafdg fabd -bedc aefbc ceadfb fdb cbagfed fecgab dcfba gaebdf cfagd bd | db bfd bfcae adgefb -cabedgf edbfgc gedcfa bacegf fde dgbf baced fd fedbc fegbc | fcdeb adbgefc adecgbf fde -fged egafc ecafgd efcda dfa dfcabg becfag fd agcdfbe ecdab | dgef fd dgfe df -deafgb gbfdc dg dbg agdc dbcafg cadfb bafced fgbce daegbfc | gbfdac afdgcb dgb gdcfb -dfecb fabdge cegbaf fdca faecb aefcdb bdf gdbce afgcebd fd | dbf fbd edcabgf fadc -cbf egabfdc fdcgba fabecd cf dfagb gfac adbegf cdegb bcfgd | acfg afgbed cgdfab fc -ebdfagc bcfa gecfdb af daegbf fgcbd bcdfag egcda fgdca gfa | fcab gafcdb dbfega acfb -adfbg eacb abfcg ecafbg gface ecfgad bc degfbc cbg gabdefc | cb gabefcd cagfebd agcbfe -ebgad bef gacfe gceadf fb efcagbd eabfcd cegfab gbfc ebagf | cefadg fcgae fgbc ebacdgf -dcg aged efacd cfgdae edacbf edfcg bcagdef gd fecbg dcfbag | cdeabgf gd gcd adge -fecgda cdabefg gabfc gfacbd ecgabf cbafe bcdef ea ace bgea | egba gabe beagfdc fbcag -bacdgf eafbd cagde becad afgcedb bc fbegad cfbe cba fcdaeb | fcbe abc dbecaf edcba -ecbdf dagfceb abcfde cbade aebgc adb bfgead debfgc cafd ad | bad dcaf begac da -gbae deafb fdgbea cegfd ag cdaefb cgabefd degfa dag dfcgab | baeg agefdb bcdafg cbdfga -ebcdf gdeafbc cdgbfe eaf cdfa deafbc gedab aecfbg ebadf af | befacd ebfda af af -cfab dcb gfedbac bc cgaedb fbdge cbfdg acgbdf gdcaf acgdfe | bc fcab afcb dbc -edbag gebdc bedfag eacdbg bcedgfa ecab ec gaedcf bdcfg cge | ce ceab ec bdegcaf -fedcba fbgca cbafge ef gbdacf efbgcad gefca befg ecdga afe | fea adgfcb fcage bcdfae -da edfgc cgfdba adfecgb gfaeb dcefga fecdgb gad gdeaf ecad | cedfg dbfcega gfcaed abdcfeg -fcgbed fcbedga cafbe gdceba bcafge bfe fagb fb eacbg facde | cdfbeg fb ebgcadf fgcedba -fecdb fdcbae afdeg cdfea aec efgbadc ca cbfa dcagbe gbefdc | facb fabc fcdbega efadcb -dagcf gadfeb ad dfegbc cgdfba dbac abgecfd dcgfb cfgae adf | fgadc cbda ad cfagd -fdgcb agedbc cdbef feac efb ef febdac afdegb abced edgafcb | fe bfecd dcebf cafe -cafdbg eaf fe gebf befcag cfbga cgaef fdaecbg edcga febacd | gfbe egbf aebgcdf faceg -bfc febg cdfga dafbec cegbd fb cdbgfe cbfgd cadegb gbefdac | dcefgb dbfcg deafbc gbdec -bacgd cedfbg cf aefc dfc aecgdf adfcgeb gafed cafgd baefdg | dgafc fc dfc gfbced -bcge fgc efcdab ecgafb cfeab fabgd fagbc bgcdeaf efcagd cg | cbeg bdagf bcgaf fgc -cdaeg fbaec ceafd fd cfd adfceb bgaecf dbcegf bdaf cgeabdf | df cdf fdagbce cbedaf -dgcbf gecfadb gbdecf gfdbca fbagde ad cdgab dag afcd caegb | cgbedf dfac bdacfeg cafdbg -defacg bd cdbegaf cfaeb dbf cbefgd cgdaf cfbgda facbd gabd | gfadec bdf gbad adgcef -bagdce deagcf bcdf cfa abgfdc cf geacfbd afgeb bacfg dcagb | cf cdbf aedcbfg fbdc -fbceda bedcf dg gefcdb aefbgd gdf cgde gfacb bdcfg dfcegab | dfbagec dfg cabdfeg gd -gda cfgbde dgbfc fgabdc fcagd cagfe baecgdf faebdg ad adbc | efgdcb dag dacb ad -dagec eca fgeacd cdefab gfdacbe afged dabgfe ac dcebg afgc | bdgce ecdga eagdc ca -da bda gadc dbafg fabgc faedcb dfcbgea agcfbe bedgf gfbadc | acbfegd gfabdc bad da -gdce aebfdg faebc fcdabg acgfedb eacgdb adc adgeb cd daceb | cd cgbadf cad edcg -caedb agbed gfbcad eca fdce gbface baefdcg acfdb fbedca ce | eac cebadf fagcdb cae -fcbadeg fcae bfdca ceb ec cdebaf ecbdf gcedab bgdfe dfagcb | geabcd acef agbced gdbeafc -cbdef degba efbad eafc dbcfge ecdafb af fcbgad edfbcag baf | gbdea ecaf eacf egfcdab -fcde gabfd cdgeba fac fc dcabe bfaced dacbf ebgfac cgfbeda | adcfb fca gebdfca fadbc -fdceg cbd edcgfa cb cdgfeb gdebac edgcafb fceb agbdf bgcfd | adfgce beacdgf bc cedfbag -fcbegda dbcefg gcebad gbfc cdb gfbaed bc cebfd ecdfa bdegf | dcb gabedf beafdg bc -cfaed bacdg egd aegcdf gcef gedac cdbefga afdgbe bdfaec eg | gcade cefad bdgfea gaedc -ac dbeacg ace defba fcaebdg dabfce abfedg dcaf cbfae efbcg | fegdba cfbae cea dbacfe -dgcaef bgcaef cfdgeb gd fgecb dcgfbae gebfd bgdc adebf fdg | gdf dafgbec dfg adfeb -ag cadg cgfed aefbc bcegdf agdfbe agf egfca gefcdba gdfeac | dgca dgcaef cdga adebcfg -dfcgbe badg aedgc eabfc dfcbega cgdafe eagbc aegcdb gbe bg | acfdge bge adbg bg -bcfage adcefg dfagc fgaec cdf abcgd dcbgafe df dfae fgcbed | df cfd eacgf fdc -cbadfe bfg cfgebd cbdg edfgbca bg egbdf feagcb fedag cefdb | fgdeb gfb fbdeca bgcd -bcde fdcgba abfcde dbfac abefc befga aec ce acfdge afdegbc | fcbad eac ec becd -ce cbagdf gdcbf cfaebdg gcbe acfdge fcdegb dbaef cef bcefd | acbgdfe cfebd gcebdf ec -ecgbd eacbf cgadeb edf ecafbdg afgebd dcgf ecfbd fgcbed fd | bcfea edf efgabcd df -dgbf egafcd cfedbag cgb abcef dcefg ebcfg cgeadb bg cgbfed | adfgebc egbcf cfeab gaefbdc -gecbfd gbedc dgabcef baefgd abegc dbfce bfdace dg gdb dfcg | dfgc bedfac dg dbg -acbdgf daeb gcbeaf gdfce adefg fbdga cbdfega fae fgdbea ea | ea fcdgaeb ae gecfadb -ga bdgafe bcaed dcgaebf bacfed acedg gbadec edgfc agd bcga | adg dga agcb fdecgab -ebdcfg cfbdg ecgabf gcd edfc fdcbeag ebcdag dabgf dc cgebf | cd gcd gacbde cd -egdfac bf afebdg baf bfdeca bgdf fedga egacb gecbafd gbeaf | bfa fb gfdb fb -gcafb dc gecd fecbgda cfdbg dfebgc cdf fbegd dcfbea fgedab | edfcbg dgbcf cd dcf -badf fcagd agcefb dfgcab ba dcbeg cedabgf abgdc acegfd abg | ebfagc dfab ab fcbdeag -cfgbad gdbfe fe efgdacb cbdge dabgfe egdcaf befa bdgfa egf | decagfb eabf baef fe -dbfea bcaefdg dcfgeb ag bfceag egfcda becfg fgeba gcab ega | agbfecd aedfcgb gcba ga diff --git a/2021/day-8.ts b/2021/day-8.ts deleted file mode 100644 index be92f2e..0000000 --- a/2021/day-8.ts +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -function split(s1: string, s2: string): [common: string, different: string] { - // Join, and count: If a character appears 2 times its common, if it appears once it's different - // and otherwise it isn't in the set. - // This works because the alphabet is known and fairly small, so we don't bother too much here. - let common: string = ''; - let different: string = ''; - const both = Array.from(s1 + s2); - for (const c of 'abcdefg') { - const count = both.reduce((s, x) => x === c ? s + 1 : s, 0); - if (count === 1) { - different += c; - } else if (count === 2) { - common += c; - } - } - return [common, different]; -} - -function recoverOutputValue(sampleDigits: string[], outputDigits: string[], debugLog: (...args: any[]) => void): number { - // Work out the various digits - function pickAndRemove(candidatePredicate: (digit: string) => boolean): string { - const candidates = sampleDigits.filter(candidatePredicate); - if (candidates.length !== 1) { - throw new Error(`Unexpected number of candidates: ${candidates.length} (should be 1)`); - } - const result = candidates[0]; - const index = sampleDigits.indexOf(result); - sampleDigits.splice(index, 1); - return result; - } - - // 1 = cf - const cf = pickAndRemove(digit => digit.length === 2); - - // 4 = cf + bd - const cfbd = pickAndRemove(digit => digit.length === 4); - - // 7 = cf + a - const cfa = pickAndRemove(digit => digit.length === 3)!; - - const a = Array.from(cfa).find(x => !cf.includes(x)); - debugLog(`Identified a: ${a}`); - - // 8 = abcdefg - const abcdefg = pickAndRemove(digit => digit.length === 7)!; - - // 6 is the one that differs by one character from 8 - 1; that difference is f, and from that we learn c - const abdeg = Array.from(abcdefg).filter(x => !cf.includes(x)).join(''); - let f; - const abdefg = pickAndRemove(digit => { - const [, different] = split(digit, abdeg); - if (different.length !== 1) { - return false; - } - f = different; - return true; - }); - debugLog(`Identified f: ${f}`); - - const c = cf[0] === f ? cf[1] : cf[0]; - debugLog(`Identified c: ${c}`); - - // 5 is the one that differs from 6 by one character, which is e - let e; - const abdfg = pickAndRemove(digit => { - const [, different] = split(digit, abdefg); - if (different.length !== 1) { - return false; - } - e = different; - return true; - }); - debugLog(`Identified e: ${e}`); - - // 9 is 5 + c - const tmp = abdfg + c; - const abcdfg = pickAndRemove(digit => { - const [, different] = split(digit, tmp); - return different.length === 0; - }); - - // 0 is the one with length 6 that isn't 9 or 6 - const abcefg = pickAndRemove(digit => digit.length === 6); - - // 3 has a single difference to 9, which is b - let b; - const acdfg = pickAndRemove(digit => { - const [, different ] = split(digit, abcdfg); - if (different.length !== 1) { - return false; - } - b = different; - return true; - }); - debugLog(`Identified b: ${b}`); - - // 2 is the one that is left over - const acdefg = pickAndRemove(() => true); - - // Build the magic mapping - // The keys are the inputs, but with the segments sorted, so that the lookup can just pick - const mapping = new Map(); - function setMapping(digit: string, value: number) { - mapping.set(Array.from(digit).sort().join(''), value); - } - function getMapping(digit: string): number { - return mapping.get(Array.from(digit).sort().join(''))!; - } - - setMapping(abcefg, 0); - setMapping(cf, 1); - setMapping(acdefg, 2); - setMapping(acdfg, 3); - setMapping(cfbd, 4); - setMapping(abdfg, 5); - setMapping(abdefg, 6); - setMapping(cfa, 7); - setMapping(abcdefg, 8); - setMapping(abcdfg, 9); - if (mapping.size !== 10) { - throw new Error(`Duplicate mappings`); - } - - let result = 0; - let power = 1; - for (let i = outputDigits.length - 1; i >= 0; i--) { - const digit = outputDigits[i]; - result += getMapping(digit) * power; - power *= 10; - } - return result; -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - const debugLog = process.env.DEBUG ? console.debug.bind(console) : () => { /* No-op */ }; - - return new Promise((resolve, reject) => { - let count1478 = 0; - let sumOutputValues = 0; - - rl.on('line', (line) => { - const [samples, output] = line.split(/\|/); - const sampleDigits = samples.trim().split(/\s+/); - const outputDigits = output.trim().split(/\s+/); - for (const digit of outputDigits) { - if ([2, 4, 3, 7].includes(digit.length)) { - count1478++; - } - } - sumOutputValues += recoverOutputValue(sampleDigits, outputDigits, debugLog); - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - console.log(`Results for ${input}: count1478 = ${count1478}, sum = ${sumOutputValues}`); - - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - '-example', - '' -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-9-example.input b/2021/day-9-example.input deleted file mode 100644 index 6dee4a4..0000000 --- a/2021/day-9-example.input +++ /dev/null @@ -1,5 +0,0 @@ -2199943210 -3987894921 -9856789892 -8767896789 -9899965678 diff --git a/2021/day-9.input b/2021/day-9.input deleted file mode 100644 index 4279e6b..0000000 --- a/2021/day-9.input +++ /dev/null @@ -1,100 +0,0 @@ -5456898789432369879876542123489327657987856789656799875436567999109876543212345679832223569876567892 -4345987678953459767989654345678916549876545689345987654323499878998765432101234599741012456997456901 -3239876565694569653298797656989301234998659793239998789019988769889887643542345987632124669984345893 -2198765464689698932129898987993212356799798910198999898998767456778998755643959876545234798763234689 -1019874323494987891034999698954324467892987891987899987859654327867899876659898989876345679854347792 -2198765654593276789126789569875455578921096999876789976749853213456899987999797899765467998765456991 -3459899986789165679297895499986587689545985789995678985432969203456789698988676789876567899886969889 -5567998999899234998989976989997688797659874568943467896541398912347991569976545679989699903999898778 -7678987899988996897679989879898799899967965679732356789699987893456932498765432578998988912398769568 -9789996989876789989567899967789912999899879789653458895987896954567893599984321367896567943987654456 -8999895678965998765456789353678999898799989898767867964596545899678974679876210256789456894596543234 -7898794567894899886567993232459887689689993919878978923985434678989865789987321347894345789987652105 -6987689879923788997678994101269776594568942101989989014974323499299976896599496579943234894298753276 -5699578989212567899789989213398667323489659232499998929865513389109987895456987689655346992129864587 -4987457893103456799898678924989543214678998943459897898756101278998998967345998798766658989239765698 -3986598954312345899986589899878994324567987894998776987543212367897999754259899969877769878999896789 -2197679298429459999875456799765889435898976799879565498656434459986899865198782156989879767889987896 -1098989197598998998964345987654768956789895989765454349867545578975789971019654345699989555978998945 -9129798998987897987653239898743457899899784378964323234978958789564688932239865456999895434567899326 -8935697899896786798761098765432345678987643265893210127989869894423567893349997569898789545678998434 -7996976798795765679872569654321267789876432123799321256792978943213456794498789689787678956789976545 -6789895987654343457983498784310456799984321012678934345694989532102457895987678997656567998999899756 -5699754698543212356694569898751287898765754123569545456789996543212345999876529876543456789999788987 -4987653987657101234569878997532345789887543234678956567893987665323456789985410989632346899987677898 -3495432398763212367789989998643457895998954345889967788942198976534569899854321296541234599876476799 -2986521019854323456794398998766568954569765676999878899959359988647999998765652987672456789434345688 -9876532198765434767899987899887678999698989989899989967898967898756789899876543498787667894321234567 -2987543459889549878998986989998989988987694496789995456987899999967898789987667569898878965210123678 -1987674678997656989887665679129998767896543345678986369896798999878954679898977679939989877325235699 -9998985889998767998766534568934987656789301234789995498765876789989543498769998998921098765434348789 -8769996999999978999654323467899876545889212345689987899654765679997659569656989897932129987845468895 -7752987899899989998785412567899986434678923676789999989543254598989798998749876766893234598876879924 -6541098998789999899876523788999875423567894567899899878932123987978987987659875845789345699987989015 -7432129997679878789987654899998765212878965678946789967891039876769896598767953234578998789598993196 -6569239876569767678998765998789984324989976789434599858992129765456797429879865347679789893459654989 -7698999988498754567899876789689765534567897895324978745789298954345689310989875498789678942578969878 -8987689987329865678945987894578987645789998974219864636678987643254569421399989569896567931345998767 -9876577895439876789236798943467898789898679765398743124567896532143478932398998678932459892459897656 -8975456989545989894345989432778999896976569876789654578978998643012389987567899789421346789598796545 -7432375678967899989459876544699987975653456998999875679699397652134567898878959894210234789989679434 -5321434567898999678978987898789876544332387899998986989543298764365689999999349954342345679876568925 -4310125678979998567899398999898965432101298934987987897659109896478998989991298765453456798765467899 -5423456789369876456789459996987896544312349549855598989798912987567987678989359886567689998654325678 -6554967895459987345996567985456789655425459659643459678987899998878996568678967987878998998763214589 -7667898979598798236789999875345678966566598998786596567986567899989987434568978998989987987654323478 -8978959768987654357899877764234999987987987659897789479875456789999876545678989799999876798765434567 -9989543657998765698998765610123889998999989543999892398754325698965987657899694678998765659876545978 -2399432648999987789999854321294678989910975432398901249987434567894598769998543567899954343997676789 -3468921237899999999989865532989789876799864321297899359876545778923459878987655679999893232498788998 -4578910345678987899879876649879998765698765410346778968987686899219678989998789789998789101349899567 -5678923456799896799767998798967899854569877621234567899498789964398989795999899898987678916467923456 -7899544567998765678946789997658899963567998799345678994329999879987897654789989987853567897878910197 -8987656978987654589897999986545789892489109998966899989910123998786789795678978986432456998989421989 -9899869899876543476789998765434576789567919887899919879891944987675678989789869864321237899996539878 -7799998767987652335578997654312345997679998766998909768799895976554564578998756979410376779987898765 -6678987654598921012469459654204456789798999854567998754656789865432123569987641988321234567899999654 -4569876432987652133578998765345567999987899968798999643245689765431012498999820987434356789998789763 -3456998521299643248689979876789878999876999989899899532124578977542127697898731976546769899987678932 -2478987654398794359799865987896989999985898992945798743012367898953234986987652988656789949876568921 -3989998785459895469898654598994399989654767891234987654123456999874349875498767898769899234998459420 -4998899899578987567997732339789239879953356899345698765674587895976659943239978919878998946987569531 -9876789988999997678986510125679198767892245978956999878765678964987898754345989324989997897898678932 -8765679876789998799876421234598987656790134567999899989899789943298979896556798735698786789999989543 -9654349865459899892987532345987898545989235678989789994929897892109467987687899645798654679899897654 -6543299764376789901297654459876789539878997889775698943210946789212389998798998789986543498789789765 -7759987853235678992998968598765798798769889997654587894321234994345678999899899898993212999655678976 -9898796542124567989899987679876899987658678998523456789532375695456899999956789956989399898534569989 -3998654321012679976789998789998999876546567895412378998943456789567989989645689349878989767623459990 -2109765442123798865678999892399799943232456789323459987656567897689878976534597959969879654312598921 -3299898765434987654587897921987689982101345895434878998767698998798967894325656798754569776454987892 -9989999876546898743456986549896549876542659986545999999898789239997856989212345679653478987579876789 -7878998989656999842345898698765434987953468999656989899979899949876745678902356798742389898989865678 -6867897698767898543476789999876323499866579998999776789954979899964634569895457972101296789998754349 -5756986549878987654579895899995439989878689987987654579793459798763123456789569863212345678989643234 -4545698756999598765689954678996998878989799876598432345689598697654234767999997654323456899875432123 -3234898767892349896896543456789887867899895987689551234578987539876345689109879765437567897988743234 -2125899898921234998954312479898766456789954698798762345689299429987456795398769897656898956797654365 -4335789989210123679869401289987654347896543479899874456792198998998878976498654998798999345698785466 -6545999878921234598998912378999865456897532567934985677999096887899989998987543239899893201349896587 -7657899867892365997887893456901977567976544878929996788998985456989999989998764347976789313499999698 -9978987654999469875456789679892988878987656989998769899987675345678929879998765456975678929989598789 -9899999769898998764365678998789899989398767899987656945976544156789219767899877567894569998765429899 -8789879898767987653234567897656789999209879998976545434965432014568998956789989698943478919896434989 -7698965999859876542123456912345678997923989987987632129876943223457897545992198789212367909998565679 -4567897898645987643934967909659899986799999896898921034989874434567895439891019894101457898679686789 -3478999987535798759899899898778965675678999785769892345698765678978999321793998943212456899598787895 -4569998796421869898776789799889873234569898643456789456789876789989998210689897654563478997689998934 -5678999654320345987655697689991982123698765432145678967894997899997896532456789876674568998798769323 -9889698764321239876543789569892993434789898543234567898943498989876987543597999987986978949899953213 -9996549895832349765432323456789876545699987654545678949232349679965498657679898798998989756999894901 -9765434998743456979521014678899999656789898765656789432101234567894329768789789659679999867999789892 -9879429899654567988734123489998978969897679896787896543212345689954219878997689943598999878989676789 -3998997698775678999645235678967867978910567987998997654324466799763206989214567892397989989879535597 -4987989459986789999856946789456456989423459998989789765436597898954345994302356789986878998965423456 -9876564345697899898767857893212347899994578989875689976598678977896459875313767898765657987654312467 -9986321234598998769878978976323456789789699876783788987899799656789967984325679999654548998743201345 -8765432347899029655989989765434568994678987655312567898919896545789898998434899998653234987654312345 -9987643456789197434699993987685678923467898742101348959102989434676789987645799876542123499875534456 -5498954567999986512567892498796989312356999863212459543219878920145678999857899987621012345989845568 -4329868678999865423456789579897893201767899974346567954334965431234568912967999876542123456798756879 diff --git a/2021/day-9.ts b/2021/day-9.ts deleted file mode 100644 index b7859d7..0000000 --- a/2021/day-9.ts +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream, writeFileSync } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -type Map = number[][]; -type Point = [row: number, column: number]; - -function findNeighbors( - map: Map, - [rowIndex, colIndex]: Point, - select: (height: number, otherHeight: number) => boolean -): Point[] { - const result: Point[] = []; - - const height = map[rowIndex][colIndex]; - - if (colIndex > 0 && select(height, map[rowIndex][colIndex - 1])) { - result.push([rowIndex, colIndex - 1]); - } - if ( - colIndex < map[rowIndex].length - 1 && - select(height, map[rowIndex][colIndex + 1]) - ) { - result.push([rowIndex, colIndex + 1]); - } - if (rowIndex > 0 && select(height, map[rowIndex - 1][colIndex])) { - result.push([rowIndex - 1, colIndex]); - } - if ( - rowIndex < map.length - 1 && - select(height, map[rowIndex + 1][colIndex]) - ) { - result.push([rowIndex + 1, colIndex]); - } - return result; -} - -function colorBasin( - map: Map, - coloredMap: Map, - openPoints: Point[], - basin: number -): number { - if (openPoints.length === 0) { - return 0; - } - - // Color the points with the basin number, and enumerate the neighbors that are same height or higher, but not 9. - function isHigherOrEqualButNot9(height: number, otherHeight: number) { - return otherHeight < 9 && otherHeight >= height; - } - - let size = 0; - while (openPoints.length > 0) { - const point = openPoints.pop()!; - const existingBasin = coloredMap[point[0]][point[1]]; - if (existingBasin !== -1) { - // Ignore this point, we've already been there. - if (existingBasin !== basin) { - throw new Error( - `Spilled into another basin (found ${existingBasin} while processing ${basin})` - ); - } - continue; - } - - coloredMap[point[0]][point[1]] = basin; - size++; - - for (const neighbor of findNeighbors( - map, - point, - isHigherOrEqualButNot9 - )) { - const existingBasin = coloredMap[neighbor[0]][neighbor[1]]; - if (existingBasin === basin) { - // Fine, ignore. - continue; - } else if (existingBasin === -1) { - // Could be interesting to look at. - openPoints.push(neighbor); - } else { - // Very much not good: We are spilling into another basin? - throw new Error( - `Would spill into another basin (found ${existingBasin} while processing ${basin})` - ); - } - } - } - - return size; -} - -function findTop3BasinSizes(map: Map, lowPoints: Point[]): number[] { - // Finding the basins: Start at each low point, and assign a basin number. Then walk upwards around it, and color each point with the basin - // number. Finally, count how many points are assigned to each basin, and pick the top 3. - const basinSizes: number[] = []; - const coloredMap: Map = map.map((row) => new Array(row.length).fill(-1)); - for (let i = 0; i < lowPoints.length; i++) { - const size = colorBasin(map, coloredMap, [lowPoints[i]], i); - basinSizes.push(size); - } - - basinSizes.sort((a, b) => a - b); - return basinSizes.slice(-3); -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - return new Promise((resolve, reject) => { - const map: Map = []; - - rl.on('line', (line) => { - map.push(line.split('').map((c) => parseInt(c, 10))); - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - const colorClasses = ` - .h4 { color: #ff4000ff; } - .h3 { color: #fd7547ff; } - .h2 { color: #fc906aff; } - .h1 { color: #faaa8dff; } - .h0 { color: #201e1fff; } - `; - - // Walk over all elements, and check that that there is a smaller neighbor - // somewhere. If there isn't, remember it as a low point. - const debugMap: string[] = []; - const lowestPointHeights: number[] = []; - const lowPoints: Point[] = []; - for (let rowIndex = 0; rowIndex < map.length; rowIndex++) { - let debugLine = ''; - const row = map[rowIndex]; - for (let colIndex = 0; colIndex < row.length; colIndex++) { - // XXX: The task isn't exactly clear, but it seems we're only a low point - // if none of our neighbors is at the same height or higher (i.e. plateaus don't count?) - function isLower(height: number, otherHeight: number) { - return otherHeight <= height; - } - - const lowerNeighbors = findNeighbors( - map, - [rowIndex, colIndex], - isLower - ).length; - let text; - const height = row[colIndex]; - if (lowerNeighbors === 0) { - lowestPointHeights.push(height); - lowPoints.push([rowIndex, colIndex]); - text = `${height}`; - } else { - text = `${height}`; - } - debugLine += `${text}`; - } - debugMap.push(debugLine); - } - const totalRiskLevel = lowestPointHeights - .map((height) => height + 1) - .reduce((s, riskLevel) => s + riskLevel, 0); - const top3BasinSizes = findTop3BasinSizes(map, lowPoints); - - console.log( - `Results for ${input}: total risk level ${totalRiskLevel}, basin indicator ${top3BasinSizes.reduce( - (p, s) => p * s, - 1 - )}` - ); - - writeFileSync( - 'day-9-debug.html', - `
${debugMap.join(
-					'\n'
-				)}
`, - 'utf-8' - ); - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - '-example', - '', -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 0d98048..0000000 --- a/package-lock.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "@ankon/adventofcode", - "version": "2021.10.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/node": { - "version": "14.17.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.34.tgz", - "integrity": "sha512-USUftMYpmuMzeWobskoPfzDi+vkpe0dvcOBRNOscFrGxVp4jomnRxWuVohgqBow2xyIPC0S3gjxV/5079jhmDg==", - "dev": true - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "tsconfig-collaborne": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/tsconfig-collaborne/-/tsconfig-collaborne-1.5.0.tgz", - "integrity": "sha512-6eq9RgG+6WguMSYlsmojoanHfRvMb88Imq81Gflb/p3EA0MWD0gIL2fNNBuMbtmaoVGVJ9DVb8rpKq+x5LTJVA==", - "dev": true - }, - "typescript": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", - "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", - "dev": true - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index b27510b..0000000 --- a/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "@ankon/adventofcode", - "version": "2021.10.0", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc -p tsconfig.json", - "watch": "tsc -p tsconfig.json -w" - }, - "author": "Andreas Kohn ", - "repository": { - "url": "https://github.com/ankon/adventofcode" - }, - "license": "ISC", - "devDependencies": { - "@types/node": "^14.17.34", - "prettier": "^2.5.1", - "source-map-support": "^0.5.21", - "tsconfig-collaborne": "^1.5.0", - "typescript": "^4.5.2" - } -} diff --git a/skeleton.ts b/skeleton.ts deleted file mode 100644 index 65d2611..0000000 --- a/skeleton.ts +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - return new Promise((resolve, reject) => { - rl.on('line', (line) => { - // Process `line` here - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - // Report results for this input - console.log(`Results for ${input}:`); - - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - '-example', - '', -]; - -main(INPUT_SPECS.map(inputSpec => `${basename(process.argv[1], extname(process.argv[1]))}${inputSpec}.input`)).catch(err => console.error(err)); diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 86e2148..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "tsconfig-collaborne", - "compilerOptions": { - "outDir": "out", - "lib": [ - "ES2019" - ] - } -} diff --git a/utils.ts b/utils.ts deleted file mode 100644 index 4569f36..0000000 --- a/utils.ts +++ /dev/null @@ -1,19 +0,0 @@ -export function qs(numbers: number[], number: number): number { - let left = 0; - let right = numbers.length; - while (right - left > 0) { - const mid = left + Math.floor((right - left) / 2); - if (number < numbers[mid]) { - right = mid; - } else if (number > numbers[mid]) { - left = mid + 1; - } else { - return mid; - } - } - return -left - 1; -} - -export function between(number: number, min: number, max: number): boolean { - return number >= min && number <= max; -} \ No newline at end of file From 4da2de09691e2a2b87393cde1866ace8b37fdc4b Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 1 Dec 2022 19:30:34 +0100 Subject: [PATCH 002/120] Add a very simple implementation of Day 1, Task 1 Especially the program structure isn't nice yet, but we keep with the go ideal of producing a self-standing binary that simply embeds it's inputs. A good start... --- .gitignore | 2 +- .vscode/launch.json | 19 + README.md | 6 + cmd/day1.go | 18 + cmd/root.go | 30 + days/1/day1.go | 52 + days/1/input.txt | 2246 +++++++++++++++++++++++++++++++++++++++++++ days/1/sample.txt | 14 + go.mod | 10 + go.sum | 11 + main.go | 7 + 11 files changed, 2414 insertions(+), 1 deletion(-) create mode 100644 .vscode/launch.json create mode 100644 cmd/day1.go create mode 100644 cmd/root.go create mode 100644 days/1/day1.go create mode 100644 days/1/input.txt create mode 100644 days/1/sample.txt create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go diff --git a/.gitignore b/.gitignore index 89f9ac0..cfa5180 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -out/ +2022 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..7c239fe --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Day 1", + "type": "go", + "mode": "debug", + "request": "launch", + "args": [ + "day1", + "--sample=false" + ], + "program": "${workspaceFolder}" + } + ] +} diff --git a/README.md b/README.md index 4950f7a..3c10262 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ # adventofcode My attempts at [saving the holidays](https://adventofcode.com/). + +## Random Thoughts and Ideas + +### Load the current task, and it's input, and auto-generate the command + +We can use the title of the day as `Short`, and the full description as `Long` to capture everything. Will need the magic of github authentication though so it grabs the correct inputs... diff --git a/cmd/day1.go b/cmd/day1.go new file mode 100644 index 0000000..8dae9c1 --- /dev/null +++ b/cmd/day1.go @@ -0,0 +1,18 @@ +package cmd + +import ( + day "github.com/ankon/adventofcode/2022/days/1" + "github.com/spf13/cobra" +) + +var day1Cmd = &cobra.Command{ + Use: "day1", + Short: "Calorie Counting", + Run: func(cmd *cobra.Command, args []string) { + day.Run(useSampleInput) + }, +} + +func init() { + rootCmd.AddCommand(day1Cmd) +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..2cadb0a --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,30 @@ +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + +// If `true` uses the sample input for the day +var useSampleInput bool + +var rootCmd = &cobra.Command{ + // XXX: `go build` bases the name on the module name, and changing that breaks people using `go get`. + // Not worth the effort right now. + Use: "2022", + Short: "Run the days of AoC 2022", +} + +func Execute() { + err := rootCmd.Execute() + if err != nil { + os.Exit(1) + } +} + +func init() { + rootCmd.PersistentFlags().BoolVar(&useSampleInput, "sample", true, "Use the sample input for the day") +} + + diff --git a/days/1/day1.go b/days/1/day1.go new file mode 100644 index 0000000..ee9fe14 --- /dev/null +++ b/days/1/day1.go @@ -0,0 +1,52 @@ +package _1 + +import ( + _ "embed" + "fmt" + "strconv" + "strings" +) + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +func findHighestCaloriesOnElf(input string) (int, error) { + var highest int + var current int + for _, line := range strings.Split(input, "\n") { + if line == "" { + if current > highest { + highest = current + } + current = 0 + } else { + calories, err := strconv.ParseInt(line, 0, 0) + if err != nil { + return 0, err + } + current += int(calories) + } + } + return highest, nil +} + +func pickInput(useSampleInput bool) string { + if useSampleInput { + return sampleInput + } else { + return fullInput + } +} + +func Run(useSampleInput bool) { + input := pickInput(useSampleInput) + highest, err := findHighestCaloriesOnElf(input) + if err != nil { + panic(err) + } + + fmt.Printf("Highest calorie count on an elf: %d\n", highest) +} diff --git a/days/1/input.txt b/days/1/input.txt new file mode 100644 index 0000000..96dba2d --- /dev/null +++ b/days/1/input.txt @@ -0,0 +1,2246 @@ +9057 +8878 +2753 +7027 +3880 +7154 +8022 +6710 +5721 + +4863 +3690 +3333 +1831 +5293 +6258 +1212 +4255 +2331 +3785 +1505 +3355 +3353 +4416 + +5918 +3076 +2145 +2712 +6087 +4310 +1084 +5807 +1342 +2770 +5095 +4696 +5842 +4555 +5388 + +20770 + +3968 +15647 +3933 +15427 +16179 + +40721 + +5837 +4419 +2159 +5173 +5215 +1991 +4842 +5642 +5435 +2853 +1055 +1667 +4361 +2316 +1974 + +24315 +6376 +6153 + +3142 +4989 +8864 +3819 +9260 +1273 +2773 + +9320 +4936 +3707 +2103 +8804 +10586 +2018 +3779 + +4129 +1019 +5054 +9429 +10526 +6314 + +13364 +14437 +14046 +7931 +11712 + +2615 +9583 +7471 +3552 +7532 +5797 +1528 +6479 +2595 + +8758 +1774 +3734 +5159 +7046 +2195 +9245 + +12116 +3801 +10950 +1935 +11450 +1091 +5891 + +7792 +4901 +9062 +8640 +6065 +6405 +3606 +2487 +6606 + +5460 +3272 +1310 +1439 +3753 +3947 +4472 +4155 +2056 +2435 +2235 +3662 +2933 +1110 +1024 + +1590 +6814 +12646 +1548 +13624 +5239 + +3955 +2469 +3104 +1548 +4551 +2307 +4450 +4491 +2233 +4706 +5950 +3395 +6592 + +17731 +18903 + +6164 +7718 +7297 +3277 +3592 +3462 +7405 +6164 +2559 +5171 +3337 + +4797 +9455 +13275 +5801 +12597 +2687 + +3091 +1153 +1733 +5022 +4441 +3163 +2375 +6388 +6061 +1444 +3255 +5828 +4414 +6171 + +2841 +17670 +14820 + +2600 +2598 +14037 +10164 + +10425 +4618 +7656 +6910 +8761 +11429 +11611 + +2787 +4826 +1527 +5024 +4252 +1393 +6744 +5665 +4601 +4129 + +6876 +8156 +7854 +6190 +5234 +8616 +1414 +1076 +5161 + +6343 +7372 +7806 +2309 +7352 +7249 +4239 +5572 +7220 +3920 +6979 + +11380 +9322 +10505 +1250 +1122 +1996 +5199 + +7569 +12600 +14729 +2514 +6841 + +9414 +9386 +10521 +4974 +11016 +11238 +1334 + +21696 +27477 + +11623 +11309 +7708 +6139 +2284 +2789 +4566 + +16850 +5171 +7647 +5516 + +24499 + +4040 +7221 +3197 +7251 +8117 +2221 +1881 +5914 +8381 + +3786 +2055 +5301 +4144 +2543 +1406 +5609 +5064 +2447 +4892 +2306 +1654 +1650 +3528 + +4187 +2576 +11910 +8331 +11613 +9093 +2752 + +4166 +6057 +4585 +1942 +5747 +3102 +2501 +4831 +5681 +6596 +4455 +1125 +4887 + +2083 +10447 +16506 + +4971 +3313 +1821 +1493 +5920 +3617 +4857 +3995 +5608 +3679 +1463 +3539 +2600 +3574 +2636 + +2804 +17188 +6966 +15585 + +13184 +15490 +9948 +14350 +12788 + +31669 + +3318 +2544 +7560 +2170 +9138 +2905 +7010 + +3933 +4835 +4704 +2140 +1896 +4951 +3870 +4241 +2819 +1065 +3605 +5667 +2361 +2642 +1926 + +6614 +3288 +3982 +7283 +7086 +2308 +3237 +7365 +6767 +6931 +5417 +5180 + +40453 + +4946 +4257 +2590 +5342 +3880 +6297 +1472 +2441 +4054 +3490 +5054 + +26102 +29920 + +3726 + +18600 +1537 +7197 +3487 + +8193 +8147 +5901 +1975 +3872 +8834 +1623 +6604 + +4501 +3385 +5321 +6771 +2517 +3943 +2744 +1330 +2277 +2344 +6399 +2090 +3571 + +8236 +6575 +6362 +3878 +7021 +8613 +3520 +3424 +2606 +5607 + +10326 +9793 +3341 +7238 +3008 +8188 +11807 + +3755 +16826 +7885 +11677 + +5980 +6793 +2393 +5757 +2525 +6496 +6420 +6902 +6755 +1023 +4226 +1451 +5006 + +6122 +3263 +4273 +2775 +2251 +1076 +2995 +5662 +4189 +2687 +5552 +6586 +2418 + +9994 +10470 +7802 +9572 +9292 +8390 +8803 +4013 + +28290 + +3210 +9126 +1346 +7538 +11536 +10544 +7409 + +20799 +16110 + +3374 +3818 +1924 +1637 +3258 +5224 +4741 +2689 +1455 +5948 +4813 +3549 +2772 +2562 +4358 + +6843 +10575 +7103 +9314 +9901 +3356 +9120 +4552 + +7709 +3977 +6868 +4640 +4665 +7109 +2662 +5682 +5388 +4256 +7249 + +69796 + +8596 +1275 +2723 +2202 +5544 +3687 +4055 +3062 +4137 +4407 + +4870 +2559 +2177 +5239 +1059 +4440 +2536 +1728 +1520 +2572 +2977 +6815 +4679 + +9042 +8883 +2705 +16255 +7889 + +2318 +4232 +1042 +3075 +6202 +7568 +2519 +5918 +1812 +3750 +3845 + +13323 +33324 + +13742 +1087 +17146 +14863 + +2686 +4132 +5052 +4751 +4695 +4528 +4801 +5741 +6027 +1754 +5633 +2427 +4679 +5777 +3143 + +1533 +4361 +2196 +10184 +3981 +6223 +9273 + +1296 +11261 +5647 +8657 +7235 +1788 + +3467 +5537 +10807 +4793 +3452 +12209 + +5745 +5137 +4002 +4824 +2655 +7597 +5748 +5931 +5264 +4469 +8009 + +4436 +4866 +3784 +5181 +6240 +6027 +3343 +5780 +2258 +6389 +3827 +6496 +6378 +4831 + +5894 +7587 +6913 +10950 +6733 +5617 +8084 + +2446 +5375 +4555 +5327 +1233 +2773 +2701 +5454 +3377 +1217 +5889 +6168 +1056 + +3468 +2402 +7848 +5652 +1448 +1954 +1021 +7860 +4305 + +2234 +17391 +5472 + +2028 +5812 +3091 +5508 +5531 +3554 +3706 +2667 +5670 +4845 +2749 +5569 +4811 +3090 +1063 + +2144 +5088 + +20000 +9957 +9049 +3092 + +12235 +6601 +3496 +16002 +1378 + +8800 +1236 +5552 +5693 +8482 +3003 +1126 +4612 +5833 +8430 + +6223 +4640 +1392 +2667 +1602 +2308 +4433 +4148 +6467 +1817 +2926 +3884 +6015 + +2273 +3007 +4509 +2902 +4170 +2731 +4409 +4873 +4237 +2667 +4243 +5788 +3673 +4582 +4696 + +27388 +26736 + +44158 + +4877 +2172 +5968 +1222 +6456 +6920 +3593 +3631 +7213 +3968 +2398 +7264 + +7126 +30978 + +4024 +2766 +2721 +2774 +2807 +1584 +2429 +3517 +5260 +4234 +2381 +5066 +4204 +4737 +4031 + +1528 +2205 +4533 +5873 +1587 +2708 +4198 +5560 +3413 +4058 +1799 +1088 +4285 +6233 + +44226 + +12933 +6090 +14830 + +5766 +2184 +2552 +4757 +1895 +2328 +1265 +5829 +2645 +6110 +6499 +5920 +6421 +2505 + +5039 +6271 +5081 +10068 +3856 +7103 + +5441 +2606 +1249 +2526 +1241 +1914 +3734 +4464 +3855 +4761 +5528 +1419 +2772 +1825 + +3554 + +8766 +2123 +7372 +7752 +6260 +5632 +3802 +9546 +7769 + +9108 +4838 + +1374 +3720 +7558 +4646 +6793 +4704 +3361 +8038 +6147 +2160 +1983 + +3133 +3621 +6073 +2533 +1644 +5277 +4276 +1921 +6251 +5273 +1571 +3769 +2155 + +2721 +3793 +4935 +2950 +2399 +1083 +4213 +4958 +1139 +1140 +2454 +3291 +3865 +1667 +4798 + +5676 +5904 +1356 +1439 +3241 +2933 +4164 +3887 +4712 +2759 +4390 +1274 +6220 +2557 + +2049 +4787 +1819 +3172 +5511 +1006 +1373 +6094 +3054 +4914 +6057 +4883 +2867 +5363 +3916 + +11348 +3724 +6793 +7336 +4032 +11297 + +4231 +4277 +2982 +2408 +5673 +6805 +4710 +7659 +6866 + +2950 +4018 +6167 +8316 +7308 +4955 +8341 +1512 +3167 +8493 + +15665 +14654 +1249 +15313 +4636 + +1494 +3325 +5902 +1393 +6813 +3900 +2827 +5936 +6589 +6847 +4658 + +11492 +14548 +5203 +15187 +5937 + +1358 +2801 +1086 +5190 +4022 +5013 +3511 +4398 +1774 +2194 +1887 +5704 +2012 +1259 + +4763 +2250 +6915 +4281 +1246 +7242 +6049 +5113 +1187 +2486 +6688 +3275 + +22345 +1336 +11325 + +6000 +3641 +1082 +2924 +5477 +3336 +4126 +3981 +5359 +1053 +4299 +5952 +4655 + +46233 + +17242 +6366 +7866 + +12504 +4031 +12664 +9756 +12750 + +3373 + +3091 +11142 +15034 +1144 +11747 + +3129 +2007 +8482 +7205 +7734 +8770 +2213 +5582 +5437 +3223 + +4471 +2591 +3286 +4446 +5388 +3600 +3357 +2644 +5028 +5569 +5055 +3284 +5597 +4116 +1076 + +3792 +2354 +8030 +3269 +2483 +1302 +7427 +6148 +3836 +7834 +1663 + +2930 +5964 +1707 +2899 +4160 +2193 +2705 +5799 +4612 +2741 +2333 +4969 +3117 +5276 +1747 + +62287 + +4321 +22825 +5690 + +7287 +1774 +4464 +2273 +2903 +8920 +4092 +8072 +8763 + +8885 +7470 +3145 +3523 +5647 +1067 +3048 + +6923 +6463 +4032 +5923 +1982 +4331 +6323 +1192 +5583 +5470 +6476 +5889 +2991 + +6697 +1560 +5520 +4516 +4845 +3035 +6047 +4906 +4596 +1934 +7245 +4476 + +4001 +7227 +5720 +3195 +8505 +6612 +4012 +4050 +8659 +3804 + +8332 +3362 +4926 +4307 +4779 +1856 +7350 +4068 +8592 +2415 + +60630 + +4263 +1716 +8004 +5253 +2004 +5381 +5614 +3020 +5985 +5587 +3563 + +18645 +10906 +3077 +2255 + +59591 + +3203 +7739 +2234 +1421 +3353 +5031 +6395 +5614 + +6259 +8748 +4341 +7788 +1074 +8497 +3996 +1294 +5197 +5779 + +10765 +5009 +3541 +2298 +10698 +13317 + +6181 +1305 +6527 +2125 +9085 +2889 +8794 +3265 +4166 + +3607 +1912 +1927 +6455 +1043 +6949 +2542 +1552 +3064 +2009 +6587 + +5574 +4632 +5869 +4312 +1703 +6124 +6479 +4556 +5917 +5890 +4949 +5614 +5576 + +2267 +7221 +5412 +5721 +2931 +3149 +6934 +3520 +6237 +4317 +1295 +6450 + +12143 +7105 +2050 +9391 +3017 +10750 + +4649 +2052 +1856 +3055 +2132 +6630 +5964 +5505 +3395 +2080 + +4388 +6963 +2613 +1055 +6588 +1348 +3752 +5538 +4524 +7994 +3977 + +5444 +6078 +8572 +10427 +5423 +3812 +1984 + +9248 +17691 +12948 +17445 + +5807 +3737 +5304 +1495 +5162 +1178 +6053 +5597 +5645 +2267 +4333 +3455 +4086 +2024 +4127 + +5502 +3665 +3494 +1502 +4702 +4563 +5216 +6486 +1931 +6493 +4618 +3960 +1149 +5109 + +2198 +1411 +4511 +1913 +4173 +4446 +6176 +2305 +4748 +4560 +4048 +5361 +4481 + +30924 + +15726 +4014 +20018 +2880 + +3345 +2576 +4787 +2186 +2156 +2989 +4400 +5147 +5393 +2830 +5869 +4839 +2860 +2134 + +2400 +2009 +2634 +4431 +7342 +5534 +2072 +5520 +5518 +2998 +3686 +4906 + +10948 +12532 +11104 +7815 + +5883 +6111 +4117 +3590 +3295 +3984 +2950 +6814 +1123 +4642 +1770 +2029 +4406 + +19302 +1549 +10378 +13976 + +4852 +7261 +4206 +12867 +8400 +11611 + +2587 +3559 +1415 +5308 +3732 +6752 +3804 +1720 +2570 +5106 +6658 +5105 +6156 + +7380 +10456 +8378 +10778 +9788 +1299 +10299 + +3596 +5969 +8288 +3025 +8196 +6410 +5966 +3060 +3015 +1270 + +14103 +5510 +13362 +19169 + +3056 +3546 +7784 +2262 +3791 +3159 +5386 +6489 +3421 +7995 +4498 + +27239 + +9345 +8921 +5252 +1154 +3189 +1175 +3216 +3282 +9392 + +2821 +7731 +8002 +1351 +5951 +4544 +3688 +4855 +8082 +1428 +5613 + +6506 +2529 +6614 +3938 +4404 +5581 +1984 +6242 +7589 + +8393 +6631 +5200 +9914 +10229 +2405 +3933 +9333 + +6766 +3486 +11457 +3098 + +5091 +4105 +1368 +4682 +3094 +4077 +5876 +1958 +1641 +3925 +2969 +3780 +5489 + +10434 +2285 +2830 +6976 +3561 +6756 + +3944 +2998 +1874 +4642 +4634 +2155 +2221 +2270 +2446 +1514 +5382 +4333 +5441 +2412 +1789 + +2433 +4036 +6005 +1551 +7281 +8466 +2141 +4190 + +5103 +6956 +5839 +2237 +7177 +6397 +11533 + +7100 +3476 +4592 +6502 +3322 +10524 +2973 +10712 + +3440 +1323 +1316 +1979 +1168 +6432 +3512 +5739 +2131 +4504 +5233 +3726 +6371 +6125 + +1917 +3442 +4104 +6123 +1657 +3139 +1690 +3323 +1269 +1407 +5603 +4819 +1787 +2340 + +11143 +9483 +9438 +12565 +7187 +13478 + +6406 +2289 +8029 +1790 +5009 +6300 +2521 + +8040 +6772 +3244 +5246 +6455 +6715 +4024 +3855 +6458 +4945 +4207 + +4628 +4872 +3344 +5675 +3761 +4467 +5113 +5746 +4140 + +9532 +1992 +5741 +8559 +4606 +6310 +5183 + +7530 +13402 +8481 +8327 + +17909 +7813 +12567 +9674 + +3329 +6032 +5539 +5513 +2555 +4767 +1085 +3329 +5138 +4448 +4082 +5569 +2732 +3326 + +2019 +3327 +3701 +3145 +1943 +1467 +1913 +5141 +7475 +7026 +4964 +2353 + +3375 +1186 +2890 +1248 +5696 +5993 +3804 +1133 +2035 +5068 +4280 +2123 +1890 + +8675 +10684 +22636 + +2704 +1093 +9357 +7940 +4843 +1118 +5533 +8943 +6492 + +67791 + +7101 +3406 +8840 +3652 +9258 +5329 +4562 +5314 +9146 + +3673 +13526 +2792 +5659 +13396 +8400 + +2492 +5265 +5244 +2173 +5032 +1182 +1486 +4561 +4673 +2480 +5148 +1375 +1093 + +1368 +5899 +6527 +7584 +2148 +2960 +7701 +5381 +6149 +2589 +7496 + +12206 +11842 +11444 +12447 + +3417 +5044 +7116 +5491 +9020 +8610 +1047 +5725 +2712 + +9153 +1836 +3337 +1686 +6044 +8786 +7476 +1688 + +17559 +10138 +16446 + +15625 +16403 +16979 +7402 + +3561 +2910 +12805 +8128 +13171 +5786 + +1332 + +1135 +5954 +9216 +5471 +3494 +9353 +6330 +4152 + +2031 +2180 +1544 +2509 +3894 +2882 +1460 +6647 +4655 +3164 +6691 +2156 +5754 + +2309 +5397 +6055 +5585 +9712 +9731 +9274 + +9865 +7291 +4863 +10688 +4135 +4572 +7321 +5603 + +1428 +5533 +4032 +1648 +1676 +5556 +1186 +4594 +5915 +2477 +4923 +5393 +2101 +2509 +1250 + +2388 +2255 +3768 +5340 +4357 +5600 +4198 +6423 +5974 +5673 +3717 +3275 +5871 +3250 + +11192 +1266 +3583 +10707 +11653 +3264 +6641 + +2009 +12343 +2394 +2147 +1560 +4352 + +5152 +6000 +6725 +3479 +1229 +1599 +3971 +6829 +8654 + +7486 +15798 +2011 +9551 +15283 + +8934 +27039 + +2048 +7506 +3661 +7298 +8557 +6387 +6496 +4471 +8596 +5325 + +1760 +2615 +1038 +9295 +6394 +7329 +5015 +4727 +9584 + +40347 + +5992 +9771 +14112 + +13049 +14348 +13202 +10630 +9351 + +8778 +9152 +10173 +8648 +4552 +4300 +5921 +9924 + +26578 +34718 + +2974 +3130 +4319 +4116 +3484 +5362 +5583 +2885 +4526 +2756 +5977 +2629 +2429 +1755 +1278 + +2848 +4821 +2207 +6922 +6699 +1999 +2354 +1922 +2133 +4496 +2510 +6509 +6929 + +5345 +3244 +2145 +1243 +1245 +2210 +5939 +3311 +6482 +5700 +3395 +2508 +3893 +6405 + +3618 +2718 +4854 +1334 +3478 +3043 +3466 +1028 +2627 +3873 +4878 +5160 +6017 +4880 +1342 + +9909 +7167 +7465 +7787 +10618 +6259 +3751 +1488 + +24782 +13684 +1905 + +5325 +9319 +7321 +6398 +8841 +3773 +2807 +9032 +2572 + +5346 +7500 +8693 +9429 +1728 +1303 +2467 +3959 +8196 + +6220 +6193 +4246 +3802 +6433 +4710 +3059 +2880 +6077 +1924 +5892 + +3421 +1973 +9474 +3990 +15878 + +6757 +9558 +9440 +8896 +5221 +3819 +6669 +1578 +7307 + +2015 +5934 +2351 +4738 +6504 +1748 +5112 +4067 +1623 +1944 +6297 +3300 +1089 + +1757 +4617 +8124 +6837 +4685 +9532 +11427 + +9094 +6552 +3882 +5341 +10752 +5572 +5882 + +5806 +3599 +1885 +4608 +6756 +4656 +1160 +4783 +2759 +3006 +3044 +5491 +6877 + +6295 +18921 +23198 + +2201 +2488 +1050 +1414 +2799 +3883 +7092 +4746 +3719 +3211 +1548 + +2656 +3600 +5148 +2300 +5547 +8226 +6952 +2611 +2268 +6490 + +5499 +8937 +12091 +1429 +9253 +2187 +2660 + +12898 + +3536 +3120 +6811 +2427 +2710 +2100 +2030 +7003 +3932 +3514 +6390 +6017 + +7645 +3909 +2219 +2290 +1401 +1812 +3180 +7733 +2547 +2653 diff --git a/days/1/sample.txt b/days/1/sample.txt new file mode 100644 index 0000000..2094f91 --- /dev/null +++ b/days/1/sample.txt @@ -0,0 +1,14 @@ +1000 +2000 +3000 + +4000 + +5000 +6000 + +7000 +8000 +9000 + +10000 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..cf2cfca --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module github.com/ankon/adventofcode/2022 + +go 1.19 + +require github.com/spf13/cobra v1.6.1 + +require ( + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f7673bd --- /dev/null +++ b/go.sum @@ -0,0 +1,11 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..ce28597 --- /dev/null +++ b/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/ankon/adventofcode/2022/cmd" + +func main() { + cmd.Execute() +} From 9e3e7042524c39881343acb934248117afdd5df1 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 1 Dec 2022 20:25:54 +0100 Subject: [PATCH 003/120] Day 1, Task 2: Playtime! Golang feels sometimes like a step back, given that I'm used to TypeScript so far. But, that also means there are chances for (re-)learning some CS basics, such as an insert-sorted topN array. --- days/1/day1.go | 73 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/days/1/day1.go b/days/1/day1.go index ee9fe14..6dfcc81 100644 --- a/days/1/day1.go +++ b/days/1/day1.go @@ -3,6 +3,7 @@ package _1 import ( _ "embed" "fmt" + "sort" "strconv" "strings" ) @@ -13,14 +14,59 @@ var sampleInput string //go:embed input.txt var fullInput string -func findHighestCaloriesOnElf(input string) (int, error) { - var highest int +type topN struct { + data []int +} + +func makeTopN(n int) topN { + data := make([]int, 0, n) + return topN{data} +} + +// Insert inserts the given value if it fits (i.e. either there is capacity left, or it is bigger than at least one existing value). +func (t *topN) Insert(v int) bool { + l := len(t.data) + + // Find the insert point + at := sort.Search(l, func(i int) bool { return v >= t.data[i] }) + + // If we get the end of the array, check whether we still have capacity. + if at == l { + if l < cap(t.data) { + t.data = append(t.data, v) + return true + } else { + return false + } + } + + // We might not be using all of the capacity yet, expand the array + dropAtEnd := 1 + if l < cap(t.data) { + t.data = append(t.data, 0) + dropAtEnd = 0 + } + + // Shift things if the insert point is not at the end + shiftLen := l - at - dropAtEnd + if shiftLen > 0 { + copy(t.data[at+1:at+1+shiftLen], t.data[at:at+shiftLen]) + } + t.data[at] = v + return true +} + +func (t *topN) Iterate() []int { + return t.data +} + +func findHighestCaloriesOnElf(input string, n int) (int, error) { + topN := makeTopN(n) + var current int for _, line := range strings.Split(input, "\n") { if line == "" { - if current > highest { - highest = current - } + topN.Insert(current) current = 0 } else { calories, err := strconv.ParseInt(line, 0, 0) @@ -30,7 +76,12 @@ func findHighestCaloriesOnElf(input string) (int, error) { current += int(calories) } } - return highest, nil + + result := 0 + for _, calories := range topN.Iterate() { + result += calories + } + return result, nil } func pickInput(useSampleInput bool) string { @@ -43,10 +94,16 @@ func pickInput(useSampleInput bool) string { func Run(useSampleInput bool) { input := pickInput(useSampleInput) - highest, err := findHighestCaloriesOnElf(input) + + highest, err := findHighestCaloriesOnElf(input, 1) if err != nil { panic(err) } - fmt.Printf("Highest calorie count on an elf: %d\n", highest) + + highest3, err := findHighestCaloriesOnElf(input, 3) + if err != nil { + panic(err) + } + fmt.Printf("Sum of the 3 highest calorie counts on an elf: %d\n", highest3) } From 12f46e676a4cc5f5eb327488b1285d19855ad8fa Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 1 Dec 2022 20:29:31 +0100 Subject: [PATCH 004/120] Simplify the logic: The initial special case isn't actually special. --- days/1/day1.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/days/1/day1.go b/days/1/day1.go index 6dfcc81..2b351fa 100644 --- a/days/1/day1.go +++ b/days/1/day1.go @@ -30,14 +30,9 @@ func (t *topN) Insert(v int) bool { // Find the insert point at := sort.Search(l, func(i int) bool { return v >= t.data[i] }) - // If we get the end of the array, check whether we still have capacity. - if at == l { - if l < cap(t.data) { - t.data = append(t.data, v) - return true - } else { - return false - } + // No space to add it, and not big enough to shift something out. + if at == cap(t.data) { + return false } // We might not be using all of the capacity yet, expand the array From 033ce8d90de821854599e0f3336df187fbb48938 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 1 Dec 2022 20:34:09 +0100 Subject: [PATCH 005/120] Remove left-over files from a mismerge --- 2021/day-15-example.input | 10 - 2021/day-15.input | 100 ------- 2021/day-15.ts | 317 ---------------------- 2021/day-16-example-1.input | 1 - 2021/day-16-example-2.input | 1 - 2021/day-16-example-3.input | 1 - 2021/day-16-example-4.input | 1 - 2021/day-16-example-literal.input | 1 - 2021/day-16-example-operator-LT0.input | 1 - 2021/day-16-example-operator-LT1.input | 1 - 2021/day-16-example-p2-1.input | 1 - 2021/day-16-example-p2-2.input | 1 - 2021/day-16-example-p2-3.input | 1 - 2021/day-16-example-p2-4.input | 1 - 2021/day-16-example-p2-5.input | 1 - 2021/day-16-example-p2-6.input | 1 - 2021/day-16-example-p2-7.input | 1 - 2021/day-16-example-p2-8.input | 1 - 2021/day-16.input | 1 - 2021/day-16.ts | 361 ------------------------- 20 files changed, 804 deletions(-) delete mode 100644 2021/day-15-example.input delete mode 100644 2021/day-15.input delete mode 100644 2021/day-15.ts delete mode 100644 2021/day-16-example-1.input delete mode 100644 2021/day-16-example-2.input delete mode 100644 2021/day-16-example-3.input delete mode 100644 2021/day-16-example-4.input delete mode 100644 2021/day-16-example-literal.input delete mode 100644 2021/day-16-example-operator-LT0.input delete mode 100644 2021/day-16-example-operator-LT1.input delete mode 100644 2021/day-16-example-p2-1.input delete mode 100644 2021/day-16-example-p2-2.input delete mode 100644 2021/day-16-example-p2-3.input delete mode 100644 2021/day-16-example-p2-4.input delete mode 100644 2021/day-16-example-p2-5.input delete mode 100644 2021/day-16-example-p2-6.input delete mode 100644 2021/day-16-example-p2-7.input delete mode 100644 2021/day-16-example-p2-8.input delete mode 100644 2021/day-16.input delete mode 100644 2021/day-16.ts diff --git a/2021/day-15-example.input b/2021/day-15-example.input deleted file mode 100644 index ab80887..0000000 --- a/2021/day-15-example.input +++ /dev/null @@ -1,10 +0,0 @@ -1163751742 -1381373672 -2136511328 -3694931569 -7463417111 -1319128137 -1359912421 -3125421639 -1293138521 -2311944581 diff --git a/2021/day-15.input b/2021/day-15.input deleted file mode 100644 index 15a36f8..0000000 --- a/2021/day-15.input +++ /dev/null @@ -1,100 +0,0 @@ -7715611621811483411121929153345417926121654738244558184333228256741518593939121351941172244538819793 -5978192582116933121967117233221363821218169348147142177193168221219699236451313112198933914323123492 -3523162115513315258921111444182316618172925755923799136271191151813516522171176112647162541858173363 -7931931461145231897547234134741682994126523123999252325119362919742719127391146114344331291116971777 -3912157144212332298711374454411326743116179131395281613188171189221945922126933817119198199326455346 -2219143418191822913131432991534835872531239119117118416185912111192962531111319326176629318111185111 -9116687994992138729148521124241932317616396617951124297314235138854797168842416251775729287611967414 -7851151594489117347687963146449123171411231791678721232616848894581346355912616826231169619235952732 -2851861191919753472141651266114831227654463284483498521612827841418971981411931436113213396426946112 -6712388671398963172123321653869646551586461492219377899341274966231951164199917165932561616983929924 -3677326111792395522936119111175266111868435913873231478188182951214919133631271356331241911265195215 -2411238217381994191274413116991994522732518981599292983991998111631182731112386631322271192212411843 -1924296312792281346181932776933796211556871296835132761484192932264311663412971542122254194197225125 -5193911629511224247133119192711512118326922142611261829118422127224838641841967498792466123922241611 -3518421332332225373982119933189183848164192326315196127257111819966291868392125511182719699513213126 -1243423697719296145178212414496848356131291919119337192521512383952691111818938552679591331194252815 -1114134841622115582771529171517131623995521325269361158192181119511123926429217441181915118546111129 -3413463671141433362959518115315279211752711714921711141946919111126196926192311117361329611368827123 -1372787612785741712553922962223999622392124621931191746293231951121499351641599723992929211182183521 -1646324114562413462565234121468141622211633146398136728423519196521422661392274137424189885124111979 -8593927754728491812319341327322619591487122534343481851326173126244497617119592817617578171431611211 -3544996545112122938226413169257256114389524779177813732798495971419433331931141513863257159222211327 -1317112599316491522993299211918262655114758519194159564179393912978824213816415221134382876196791131 -2992415411131212997526331872111112996344865592792815133565817171814172837534233288248214812739937128 -7399281754443127946141431876481961612345132118851715323452891116597132773351188234354812269914136314 -1353222121126771342784863118971948121131151269737693294597543471364852531536931711275612918142912339 -1231143322424173511217841979211499894524361726733118828862941949323516193769441834412128333517121219 -4153113123817117759341379297738315498194824968743168793739217211372842125911549919617297111441613631 -9731976338891216952882213198614419772196764362991958541418412247316741111113414519698991177561491619 -1549968122497536224817279413173193149141335731431114111191969373537193295361951832648538349971115651 -3141199162911153239685453949619182151714537212236218628247835892234915714197151176914515494168817613 -2321634214222164696761674371984136262645585522114118771793891255516343661843273111241429184252481112 -1323271335941123627134295288123814147892434111122433863111883333942311312165717429336197351684297515 -1799383479828119861997991252537621715111112211243118199888781621163257948541164311576771111337441297 -3474558728714311424212121852197696651899775852781115664112735924716128287452112718142116441487711179 -1212211282414612598188336251113541918828321262911122168152739929958181711329326391542161816879229457 -9369141739122111275981911719178226989791269152711118514211312351951888312115211119912146165111417274 -1557942397217218772114458897214197121496239971221799298121731791112838411839164943531148113513822329 -2116511928331138153519713938955192461891971295394211113118549975869129341915148999142791221429844338 -1216615164189449189844291299217862321339427481291811189889121368125354184186711881158278233714798812 -2131462662132519141953391411117681836144434719816111765876594111661972132119291718521288742511921812 -1352178182113553243431145717611728111429117626322671124512968719613828222757811142112237112915916411 -9111861843583342173156761182486951611273911221233459621981815173222733765922411929621144273182167173 -6461614968141185513751845166496129581174136991312882746411333574211232145145411259791494747636513831 -8395826326831481781816141231151946694412171233118734118443712934188141261953428112498397283833996953 -3224325116954176581173265389433772885221125196135137181681253382516579111971122321919261361455573426 -5612711314828933927115772517317242878121717862126961211324793885131324871781627863678621349344985162 -9219113183181524712318355994194342313255174114168321236494161659235237996744938323416519175154774368 -1455219173629652263128124278132571923466188331613694112619643242969214341411691592236981126229531246 -9997212872235551519294812463451816576987351769737341319699248495132218138849526591159541452141311227 -9439551788914742428219371619927339189298769319132111753411511544151872351486489786185314584942895521 -4623921912121114189211698941781144517423493925244616879259454219595112526216227151411539965913122341 -9233881249291833812284319142291868129327632421241354425437738985391254261131535339322529281581561495 -6621816747917191382495161833567118397773372129721681832591214252274233112632684542595451911924821133 -1961985912891945611341231799388123719733816334154627934522422918536573253556769424412919116426182323 -8613914491619713822131419117143163659542154519169992171969135131941141557529457324123161951111765294 -4268219915611518484714151351482241221275914371738124149239386327831219359136247361161375174224223839 -2417628752221923911251535153892648194748229231761133182371314159657511173541128258975114145282143131 -1149132123898111199247912341113411962434312877836882119771691759571972141321747138787951211139182122 -8589114128711558917336937119159115193482491549524442733618822133531142619542652131192519259679572118 -8417549457115646563131638317315161112292939814589243166226251236828614439212129983319595172328298496 -7132261193213112392744229915239441239812134161721522541289116993632721981519211498478878212229136195 -5284114931928992331114192299645884318993264292231979919528343172899594924111575491982184914671211943 -4138427142832314543311113423227271112997816549131893391237171313241261242672582112128835619821371121 -4918821233299337972289281128133411678349812271421157479832992298658193248154113222111521996724714323 -9174191481421563857184797521172297912449121127431641255195914981149724121258184197136514813734273234 -4112626214511388118211446512388876694313187965929168166814111113382224115821767413172111376427638393 -3231154459742912972641231118291138185681466529142819182885451441118191771984959111111623683628161113 -5841171953222465917336112439651628888517153249964599148991263916813419222189131513441336935294361738 -1816982764214991569342131547714487273197791551197149221141426622298772319696223747144351291172292314 -9475574461545913358168363336339111314873371711345178219127111194927223149613171931929322893211152758 -4858113211241899116852635135769311112114182724528552311872195867129114349887193381564631182288641431 -9742923193935298412422519924115919956189443126116429369399671331114348991891115412454184715126299998 -9121814433419188117111757994391996912918393911152421324919462957262487176581182129438199211342711241 -9152171557731172939156141661228213792961792411377162925187423286231921473559751361928233131516412191 -7288111938512228994743624943311448872522112536176928681443419899213241329198212953522514116811911197 -9349832181421346375192594111125921597518122235122992135833853191479358257121815429654613383832118393 -5787987676213718162591455312614145484267395142381485479118249352234818169546988191111121531915975846 -1593328873913943873678371287612191117251139167998756142661344997618573521246115295381218111199353123 -7792811294182231635163292331735316144325221519124512326112978344515322371153671145111948211314111961 -2318518221984644229891593834523191322527124556185113492672653928784664122218293847186517161551631851 -1112829983141931112651721133161412432143348121156512484214145542131639818492551211129611431998577181 -3592613729447389151192925815192425191916611234864255478391561193394996337454189464938128832119348811 -1271921732441182191447179913999221292183221141274914288646297111212268851116317378213664353119951955 -1952724641973599331362393291821311217123755111853629765725951319311313197419922547371189952219569671 -9175174929918626863191261492871635282719323944341514814391991254113352393192263965371316169319756114 -7796162132715959911612986171614281934119795141614191521216692472181723351815721531573126767456111621 -1929441344612524315169915972256329374194651851188791336975193211635164981382125948798143115991218147 -3196918124398432195448219783729332721415743182553947677319291263569111194212214141296123149311195918 -3158114419662114389969334121776231616687394316562465952127448362341922599962916219531841316418231911 -7689421696457392537729119321129879691967715569123191226313319112314943111466159111416157881113611939 -7831513935396926282212738725323211942958912226993621996662133721199282226293728546453712751822771285 -2123699211953181196938911293262179311281131944194219219814973246548631519123711749121712622686521314 -5191342118926287865138111129119915719811398331646995511667311198221618374236169145912891632927912111 -8214442493117223193442175221522611659488871176512331552482329112125141241921222999759248511345262843 -1914183724394277228911926796911512739125432271261643511196439716723711131491717732211162514393511298 -1119745958685726562282127671296828241734389837168591468985891281128335925991724159212218314375287914 -9517519684395161899187861919321914215994991181859919191641351832193212127643354718852685876126577315 -3342917922251914252338185581691191842316989111841311466776912683629971312998965551711141287138724241 -8176221727998313186834559714891971413547985825489911732617146966111238282644811394895278181837711185 diff --git a/2021/day-15.ts b/2021/day-15.ts deleted file mode 100644 index 90ee84f..0000000 --- a/2021/day-15.ts +++ /dev/null @@ -1,317 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -const PRINT_MAZE = process.env.PRINT_MAZE ?? false; -const COLUMNS = parseInt(process.env.COLUMNS ?? '80', 10); - -type Pos = [row: number, col: number]; - -/** 2D structure with costs to enter a particular tile */ -type Maze = number[][]; - -/** Node inside the open/closed lists */ -interface Node { - pos: Pos; - cost: number; - estimatedCost: number; - path: Pos[]; -} - -function costAt(maze: Maze, [row, col]: Pos): number { - const l = maze.length; - const firstTileRow = row % l; - const firstTileCol = col % l; - const firstTileCost = maze[firstTileRow][firstTileCol]; - return ( - ((firstTileCost + Math.floor(row / l) + Math.floor(col / l) - 1) % 9) + - 1 - ); -} - -function printMaze( - maze: Maze, - open: Node[], - closed: number[][], - [maxRow, maxCol]: Pos, - path?: Pos[] -) { - if (!PRINT_MAZE) { - return; - } - // Draw the maze, possibly highlighting the path - function label(pos: Pos, cost: number): string { - if (path) { - const pathIndex = path.findIndex( - ([row, col]) => pos[0] === row && pos[1] === col - ); - if (pathIndex > -1) { - return pathIndex === path.length - 1 - ? `>${cost}<` - : `.${cost}.`; - } - } - const isOpen = - open.findIndex( - ({ pos: [row, col] }) => pos[0] === row && pos[1] === col - ) > -1; - if (isOpen) { - return `(${cost})`; - } - const isClosed = closed[pos[0]][pos[1]] !== Number.MAX_SAFE_INTEGER; - if (isClosed) { - return ` ${cost} `; - } - return ` ${cost} `; - } - - for (let row = 0; row < maxRow + 1; row++) { - let line = ''; - for (let col = 0; col < maxCol + 1; col++) { - line += label([row, col], costAt(maze, [row, col])); - } - console.log(line); - } -} - -function costPerStepEstimatePathAverage(path: Pos[], maze: Maze) { - if (path.length === 0) { - return 1; - } else { - const costOfPath = path.reduce( - (c, [row, col]) => c + maze[row][col], - 0 - ); - return costOfPath / path.length; - } -} - -function costPerStepEstimateConstant() { - return 1; -} - -/** Estimate the costs between `from` and `to` */ -function estimateCost( - maze: Maze, - from: Pos, - to: Pos, - pathToFrom: Pos[], - costPerStepEstimate: (path: Pos[], maze: Maze) => number -): number { - const requiredSteps = - Math.abs(to[0] - from[0] + 1) + Math.abs(to[1] - from[1] + 1); - return requiredSteps * costPerStepEstimate(pathToFrom, maze); -} - -/** - * Find the cheapest path from `from` to `to` and return the cost of that - * - * @param maze - */ -function findPath( - maze: Maze, - to: Pos, - costPerStepEstimate: (path: Pos[], maze: Maze) => number -): number { - const from: Pos = [0, 0]; - const open: Node[] = [ - { - pos: from, - cost: 0, - estimatedCost: estimateCost( - maze, - from, - to, - [], - costPerStepEstimate - ), - path: [from], - }, - ]; - const closed: number[][] = []; - for (let row = 0; row < to[0] + 1; row++) { - closed.push(new Array(to[1] + 1).fill(Number.MAX_SAFE_INTEGER)); - } - - let steps = 0; - while (open.length > 0) { - // Pick (and remove) the open node with the lowest total (up-to + estimated) cost - const cheapestIndex = open.reduce( - (r, _n, i) => - open[r].cost + open[r].estimatedCost <= - open[i].cost + open[i].estimatedCost - ? r - : i, - 0 - ); - const cheapest = open.splice(cheapestIndex, 1)[0]; - - if (steps % 1000 === 0) { - printMaze( - maze, - open, - closed, - [Math.min(to[0], 25), Math.min(to[1], COLUMNS)], - cheapest.path - ); - console.debug( - `After ${steps} steps: ${cheapest.path.length} length, ${cheapest.cost} so far, ${cheapest.estimatedCost} still to go` - ); - } - steps++; - - // Generate the successors (non-diagonal) - for (const delta of [ - [-1, 0], - [0, 1], - [1, 0], - [0, -1], - ]) { - const successorPos: Pos = [ - cheapest.pos[0] + delta[0], - cheapest.pos[1] + delta[1], - ]; - if ( - successorPos[0] < 0 || - successorPos[0] > to[0] || - successorPos[1] < 0 || - successorPos[1] > to[1] - ) { - // Not on the map - continue; - } - - const successorCost = cheapest.cost + costAt(maze, successorPos); - // 1. hit the end? then this must be the cheapest path - if (successorPos[0] === to[0] && successorPos[1] === to[1]) { - console.log(`Path at ${successorCost}`, cheapest.path); - return successorCost; - } - - // 2. pos is already in the open list? if that is cheaper ignore this, otherwise replace - // 3. pos is already in the closed list? if that is cheaper ignore this, otherwise add to open - const successorPath = [...cheapest.path, successorPos]; - const successorEstimatedCost = estimateCost( - maze, - successorPos, - to, - successorPath, - costPerStepEstimate - ); - const successor = { - pos: successorPos, - cost: successorCost, - estimatedCost: successorEstimatedCost, - path: successorPath, - }; - const openSuccessorIndex = open.findIndex( - ({ pos: p }) => - p[0] === successorPos[0] && p[1] === successorPos[1] - ); - if (openSuccessorIndex > -1) { - // This position exists, check whether we found a cheaper or at least equally - // expensive shorter path to it. - if ( - open[openSuccessorIndex].cost + - open[openSuccessorIndex].estimatedCost >= - successorCost + successorEstimatedCost - ) { - if ( - open[openSuccessorIndex].path.length > - successor.path.length - ) { - open[openSuccessorIndex] = successor; - } - } - continue; - } - if ( - closed[successorPos[0]][successorPos[1]] <= - successorCost + successorEstimatedCost - ) { - // No point to look at this, we have been here before with a lower cost already. - continue; - } - - // Add to the open list to check it. - open.push(successor); - } - - // Remember that we have been here. - closed[cheapest.pos[0]][cheapest.pos[1]] = - cheapest.cost + cheapest.estimatedCost; - } - - throw new Error('No open nodes left, but end not found?'); -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - return new Promise((resolve, reject) => { - const maze: Maze = []; - - rl.on('line', (line) => { - maze.push(Array.from(line.trim()).map((c) => parseInt(c, 10))); - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - let costPerStepEstimate; - switch (process.env.ESTIMATOR) { - case 'avg': - costPerStepEstimate = costPerStepEstimatePathAverage; - break; - case 'constant': - default: - costPerStepEstimate = costPerStepEstimateConstant; - break; - } - // NB: Maze is square by definition - const riskLevel = findPath( - maze, - [maze.length - 1, maze.length - 1], - costPerStepEstimate - ); - const riskLevelPart2 = findPath( - maze, - [maze.length * 5 - 1, maze.length * 5 - 1], - costPerStepEstimate - ); - console.log( - `Results for ${input}: part1 = ${riskLevel}, part2 = ${riskLevelPart2}` - ); - - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - '-example', - '', -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); diff --git a/2021/day-16-example-1.input b/2021/day-16-example-1.input deleted file mode 100644 index 0d2cbff..0000000 --- a/2021/day-16-example-1.input +++ /dev/null @@ -1 +0,0 @@ -8A004A801A8002F478 diff --git a/2021/day-16-example-2.input b/2021/day-16-example-2.input deleted file mode 100644 index ed3b78a..0000000 --- a/2021/day-16-example-2.input +++ /dev/null @@ -1 +0,0 @@ -620080001611562C8802118E34 diff --git a/2021/day-16-example-3.input b/2021/day-16-example-3.input deleted file mode 100644 index 5ec2dac..0000000 --- a/2021/day-16-example-3.input +++ /dev/null @@ -1 +0,0 @@ -C0015000016115A2E0802F182340; diff --git a/2021/day-16-example-4.input b/2021/day-16-example-4.input deleted file mode 100644 index 17230e3..0000000 --- a/2021/day-16-example-4.input +++ /dev/null @@ -1 +0,0 @@ -A0016C880162017C3686B18A3D4780; diff --git a/2021/day-16-example-literal.input b/2021/day-16-example-literal.input deleted file mode 100644 index 4a47c0e..0000000 --- a/2021/day-16-example-literal.input +++ /dev/null @@ -1 +0,0 @@ -D2FE28; diff --git a/2021/day-16-example-operator-LT0.input b/2021/day-16-example-operator-LT0.input deleted file mode 100644 index a7f8f25..0000000 --- a/2021/day-16-example-operator-LT0.input +++ /dev/null @@ -1 +0,0 @@ -38006F45291200 diff --git a/2021/day-16-example-operator-LT1.input b/2021/day-16-example-operator-LT1.input deleted file mode 100644 index bcc798c..0000000 --- a/2021/day-16-example-operator-LT1.input +++ /dev/null @@ -1 +0,0 @@ -EE00D40C823060 diff --git a/2021/day-16-example-p2-1.input b/2021/day-16-example-p2-1.input deleted file mode 100644 index adfbea0..0000000 --- a/2021/day-16-example-p2-1.input +++ /dev/null @@ -1 +0,0 @@ -C200B40A82; diff --git a/2021/day-16-example-p2-2.input b/2021/day-16-example-p2-2.input deleted file mode 100644 index 08def75..0000000 --- a/2021/day-16-example-p2-2.input +++ /dev/null @@ -1 +0,0 @@ -04005AC33890 diff --git a/2021/day-16-example-p2-3.input b/2021/day-16-example-p2-3.input deleted file mode 100644 index c4d0ebb..0000000 --- a/2021/day-16-example-p2-3.input +++ /dev/null @@ -1 +0,0 @@ -880086C3E88112 diff --git a/2021/day-16-example-p2-4.input b/2021/day-16-example-p2-4.input deleted file mode 100644 index 985c72d..0000000 --- a/2021/day-16-example-p2-4.input +++ /dev/null @@ -1 +0,0 @@ -CE00C43D881120 diff --git a/2021/day-16-example-p2-5.input b/2021/day-16-example-p2-5.input deleted file mode 100644 index 408badd..0000000 --- a/2021/day-16-example-p2-5.input +++ /dev/null @@ -1 +0,0 @@ -D8005AC2A8F0 diff --git a/2021/day-16-example-p2-6.input b/2021/day-16-example-p2-6.input deleted file mode 100644 index eb83c7b..0000000 --- a/2021/day-16-example-p2-6.input +++ /dev/null @@ -1 +0,0 @@ -F600BC2D8F diff --git a/2021/day-16-example-p2-7.input b/2021/day-16-example-p2-7.input deleted file mode 100644 index 6055bef..0000000 --- a/2021/day-16-example-p2-7.input +++ /dev/null @@ -1 +0,0 @@ -9C005AC2F8F0 diff --git a/2021/day-16-example-p2-8.input b/2021/day-16-example-p2-8.input deleted file mode 100644 index 4ced67a..0000000 --- a/2021/day-16-example-p2-8.input +++ /dev/null @@ -1 +0,0 @@ -9C0141080250320F1802104A08 diff --git a/2021/day-16.input b/2021/day-16.input deleted file mode 100644 index 1c38429..0000000 --- a/2021/day-16.input +++ /dev/null @@ -1 +0,0 @@ -A20D790042F1274011955491808B802F1C60B20030327AF2CC248AA800E7CDD726F3D78F4966F571A300BA54D668E2519249265160803EA9DE562A1801204ACE53C954ACE53C94C659BDF318FD1366EF44D96EB11005FB39154E0068A7C3A6B379646C80348A0055E6642B332109B8D6F0F12980452C9D322B28012EC72D51B300426CF70017996DE6C2B2C70C01A04B67B9F9EC8DAFE679D0992A80380104065FA8012805BD380120051E380146006380142004A00E920034C0801CA007B0099420053007144016E28018800CCC8CBB5FE79A3D91E1DC9FB151A1006CC0188970D6109803B1D61344320042615C198C2A014C589D00943096B3CCC081009173D015B004C401C8E10421E8002110BA18C193004A52257E0094BCE1ABB94C2C9005112DFAA5E80292B405927020106BC01494DFA6E329BF4DD273B69E233DB04C435BEF7A0CC00CFCDF31DC6AD20A3002A498CC01D00042229479890200E4438A91700010F88F0EA251802D33FE976802538EF38E2401B84CA05004833529CD2A5BD9DDAC566009CC33E8024200CC528E71F40010A8DF0C61D8002B5076719A5D418034891895CFD320730F739A119CB2EA0072D25E870EA465E189FDC1126AF4B91100A03600A0803713E2FC7D00043A25C3B8A12F89D2E6440242489A7802400086C788FB09C0010C8BB132309005A1400D2CBE7E7F2F9F9F4BB83803B25286DFE628E129EBCB7483C8802F3D0A2542E3004AC0169BD944AFF263361F1B48010496089807100BA54A66675769B1787D230C621EF8B9007893F058A009AE4ED7A5BBDBE05262CEC0002FC7C20082622E0020D0D66A2D04021D5003ED3D396E19A1149054FCA3586BD00020129B0037300042E0CC1184C000874368F70A251D840239798AC8DC9A56F7C6C0E0728015294D9290030B226938A928D0 diff --git a/2021/day-16.ts b/2021/day-16.ts deleted file mode 100644 index 31e81fa..0000000 --- a/2021/day-16.ts +++ /dev/null @@ -1,361 +0,0 @@ -#!/usr/bin/env node - -import { createReadStream } from 'fs'; -import { basename, extname } from 'path'; -import { createInterface } from 'readline'; - -class Bitstream { - private consumedLength = 0; - - constructor( - private data: Buffer, - /** Offset (in bits) */ - private offset = 0, - /** Maximum number of bits to consume */ - private length = data.length * 8 - ) {} - - private consume(length: number) { - if (this.consumedLength + length > this.length) { - throw new Error( - `Cannot consume ${length} bits (only ${this.available} available)` - ); - } - this.consumedLength += length; - } - - public get available() { - return this.length - this.consumedLength; - } - - public readBitstream(length: number): Bitstream { - this.consume(length); - - const result = new Bitstream(this.data, this.offset, length); - this.offset += length; - return result; - } - - /** Read the next `num` bits and return the value */ - public readBits(num: number): number { - this.consume(num); - - let result = 0; - // TODO: We could special-case the situation where we need more than a byte - // by first proceeding to the full next byte, then grab bytes until we need - // an incomplete byte, and then grab the remaining bits. - while (num > 0) { - const byteOffset = Math.floor(this.offset / 8); - // Grab the byte we need, mask off the needed bits and put them into our number - const byte = this.data[byteOffset]; - - /** Number of bits to shift the result left */ - let consumedBits = 0; - /** Mask for picking the right bits from byte */ - let mask = 0; - - /** First bit in this byte we're looking at */ - let firstBit = this.offset % 8; - for (let bit = firstBit; bit < 8; bit++) { - mask <<= 1; - if (num > 0) { - mask |= 1; - consumedBits++; - num--; - } - } - this.offset += consumedBits; - - const rawBits = byte & mask; - const rawBitsShift = 8 - firstBit - consumedBits; - result = (result << consumedBits) | (rawBits >>> rawBitsShift); - } - return result; - } - - public readVersion() { - return this.readBits(3); - } - - public readType() { - return this.readBits(3); - } - - /** - * Read a literal value - */ - public readLiteralValue() { - /** Bit mask for the "has next" bit */ - const HAS_NEXT_BIT = 1 << 4; - /** - * Multiplier for each chunk of 4 bits - * Bit operations in JavaScript are signed 32bit operations, so we cannot arbitrarily - * shift left by 4. Instead we replace `(result<<4)|chunk` with `result*MULTIPLIER+chunk`. - */ - const MULTIPLIER = 1 << 4; - let result = 0; - // For debugging to set conditional breakpoints and verify the result - // let debugStartOffset = this.offset; - // let debugBits = ''; - let hasNext; - do { - const bits = this.readBits(5); - hasNext = (bits & HAS_NEXT_BIT) === HAS_NEXT_BIT; - const chunk = bits & 0xf; - result = result * MULTIPLIER + chunk; - // debugBits += (bits & 0xf).toString(2).padStart(4, '0'); - } while (hasNext); - // assert parseInt(debugBits, 2) === result - return result; - } -} - -const PT_OP_SUM = 0; -const PT_OP_PRODUCT = 1; -const PT_OP_MIN = 2; -const PT_OP_MAX = 3; -/** Known packet type for "literal value" */ -const PT_LITERAL = 4; -const PT_OP_CMP_GT = 5; -const PT_OP_CMP_LT = 6; -const PT_OP_CMP_EQ = 7; - -interface Packet { - version: number; - type: number; -} - -interface LiteralValue extends Packet { - value: number; -} - -interface Operator extends Packet { - operands: Packet[]; -} - -interface Comparison extends Omit { - operands: [left: Packet, right: Packet]; -} - -function parse(bitstream: Bitstream): Packet { - const version = bitstream.readVersion(); - const type = bitstream.readType(); - if (type === PT_LITERAL) { - // A literal (shouldn't happen as top-level) - const value = bitstream.readLiteralValue(); - const result: LiteralValue = { - version, - type, - value, - }; - return result; - } else { - // Some operator, so the next part defines how to walk through it - const operands: Packet[] = []; - const lengthType = bitstream.readBits(1); - if (lengthType === 0) { - const totalLengthInBits = bitstream.readBits(15); - const slice = bitstream.readBitstream(totalLengthInBits); - while (slice.available) { - operands.push(parse(slice)); - } - } else { - const numSubPackets = bitstream.readBits(11); - for (let i = 0; i < numSubPackets; i++) { - operands.push(parse(bitstream)); - } - } - - const result: Operator = { - version, - type, - operands, - }; - return result; - } -} - -function isLiteralValue(packet: Packet): packet is LiteralValue { - return packet.type === PT_LITERAL; -} - -function isOperator(packet: Packet): packet is Operator { - return packet.type !== PT_LITERAL; -} - -function isComparison(packet: Operator): packet is Comparison { - return [PT_OP_CMP_EQ, PT_OP_CMP_GT, PT_OP_CMP_LT].includes(packet.type); -} - -function calculateVersionSum(packet: Packet): number { - if (isLiteralValue(packet)) { - return packet.version; - } else if (isOperator(packet)) { - return ( - packet.version + - packet.operands.reduce((s, p) => s + calculateVersionSum(p), 0) - ); - } - throw new Error('Unexpected packet'); -} - -function calculateOperationValue(packet: Operator): number { - if (isComparison(packet)) { - let compare: (left: number, right: number) => boolean; - switch (packet.type) { - case PT_OP_CMP_EQ: - compare = (left, right) => left === right; - break; - case PT_OP_CMP_GT: - compare = (left, right) => left > right; - break; - case PT_OP_CMP_LT: - compare = (left, right) => left < right; - break; - default: - throw new Error(`Unexpected comparison ${packet.type}`); - } - return compare( - calculateExpression(packet.operands[0]), - calculateExpression(packet.operands[1]) - ) - ? 1 - : 0; - } - - let reducer: (r: number, o: number) => number; - let initial: number; - switch (packet.type) { - case PT_OP_SUM: - reducer = (s, o) => s + o; - initial = 0; - break; - case PT_OP_PRODUCT: - reducer = (s, o) => s * o; - initial = 1; - break; - case PT_OP_MIN: - reducer = (s, o) => (s < o ? s : o); - initial = Number.POSITIVE_INFINITY; - break; - case PT_OP_MAX: - reducer = (s, o) => (s > o ? s : o); - initial = Number.NEGATIVE_INFINITY; - break; - default: - throw new Error(`Unexpected operation ${packet.type}`); - } - - return packet.operands.map(calculateExpression).reduce(reducer, initial); -} - -function calculateExpression(packet: Packet): number { - if (isLiteralValue(packet)) { - return packet.value; - } else if (isOperator(packet)) { - return calculateOperationValue(packet); - } - throw new Error('Unexpected packet'); -} - -function printExpression(packet: Packet): string { - if (isLiteralValue(packet)) { - return String(packet.value); - } else if (isOperator(packet)) { - let opName = { - [PT_OP_SUM]: 'Sum', - [PT_OP_PRODUCT]: 'Product', - [PT_OP_MIN]: 'Min', - [PT_OP_MAX]: 'Max', - [PT_OP_CMP_LT]: 'Lt', - [PT_OP_CMP_GT]: 'Gt', - [PT_OP_CMP_EQ]: 'Eq', - }[packet.type]; - return `${opName}(${packet.operands.map(printExpression).join(', ')})`; - } - throw new Error('Unexpected packet'); -} - -function processInput(input: string): Promise { - const rl = createInterface(createReadStream(input)); - - return new Promise((resolve, reject) => { - let data: Buffer = Buffer.alloc(0); - rl.on('line', (line) => { - // Parse the line as hex-encoded data, and concat it - // The concat isn't strictly needed, because it seems there is only one line - // coming, but it doesn't hurt. - data = Buffer.concat([data, Buffer.from(line, 'hex')]); - }); - rl.on('error', (err) => { - reject(err); - }); - rl.on('close', () => { - const packet = parse(new Bitstream(data)); - const versionSum = calculateVersionSum(packet); - const expressionValue = calculateExpression(packet); - console.log( - `Results for ${input}: ${printExpression( - packet - )} = ${expressionValue} (version sum ${versionSum})` - ); - - resolve(); - }); - }); -} - -async function main(inputFiles: string[]) { - for (const inputFile of inputFiles) { - try { - await processInput(inputFile); - } catch (err: any) { - console.error(`Cannot process ${inputFile}: ${err.message}`); - } - } -} - -const INPUT_SPECS = [ - // - // Literal 2021 - // '-example-literal', - // Op [10, 20] - // '-example-operator-LT0', - // Op [1, 2, 3] - // '-example-operator-LT1', - // Version sum 16 - // '-example-1', - // Version sum 12 - // '-example-2', - // Version sum 23 - // '-example-3', - // Version sum 31 - // '-example-4', - // Sum(1, 2) - '-example-p2-1', - // Product(6, 9) - '-example-p2-2', - // Min(6, 7, 8) - '-example-p2-3', - // Max(6, 7, 8) - '-example-p2-4', - // Lt(5, 15) - '-example-p2-5', - // Lt(15, 5) - '-example-p2-6', - // Eq(5, 15) - '-example-p2-7', - // Eq(Sum(1, 3), Product(2, 2)) - '-example-p2-8', - '', -]; - -main( - INPUT_SPECS.map( - (inputSpec) => - `${basename( - process.argv[1], - extname(process.argv[1]) - )}${inputSpec}.input` - ) -).catch((err) => console.error(err)); From 1c3c2d656582a014a16f16d8530e63ebf1ef8af3 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 2 Dec 2022 09:06:38 +0100 Subject: [PATCH 006/120] Day 2, Task 0: Restructure and prepare For now let's move all cobra command definitions into a single file, as these are most likely going to end up copy-pastes of each other (or something smarter ...). --- cmd/day1.go | 18 - cmd/days.go | 29 + days/2/day2.go | 24 + days/2/input.txt | 2500 +++++++++++++++++++++++++++++++++++++++++++++ days/2/sample.txt | 3 + 5 files changed, 2556 insertions(+), 18 deletions(-) delete mode 100644 cmd/day1.go create mode 100644 cmd/days.go create mode 100644 days/2/day2.go create mode 100644 days/2/input.txt create mode 100644 days/2/sample.txt diff --git a/cmd/day1.go b/cmd/day1.go deleted file mode 100644 index 8dae9c1..0000000 --- a/cmd/day1.go +++ /dev/null @@ -1,18 +0,0 @@ -package cmd - -import ( - day "github.com/ankon/adventofcode/2022/days/1" - "github.com/spf13/cobra" -) - -var day1Cmd = &cobra.Command{ - Use: "day1", - Short: "Calorie Counting", - Run: func(cmd *cobra.Command, args []string) { - day.Run(useSampleInput) - }, -} - -func init() { - rootCmd.AddCommand(day1Cmd) -} diff --git a/cmd/days.go b/cmd/days.go new file mode 100644 index 0000000..7b93b79 --- /dev/null +++ b/cmd/days.go @@ -0,0 +1,29 @@ +package cmd + +import ( + day1 "github.com/ankon/adventofcode/2022/days/1" + day2 "github.com/ankon/adventofcode/2022/days/2" + + "github.com/spf13/cobra" +) + +var day1Cmd = &cobra.Command{ + Use: "day1", + Short: "Calorie Counting", + Run: func(cmd *cobra.Command, args []string) { + day1.Run(useSampleInput) + }, +} + +var day2Cmd = &cobra.Command{ + Use: "day2", + Short: "Rock Paper Scissor", + Run: func(cmd *cobra.Command, args []string) { + day2.Run(useSampleInput) + }, +} + +func init() { + rootCmd.AddCommand(day1Cmd) + rootCmd.AddCommand(day2Cmd) +} diff --git a/days/2/day2.go b/days/2/day2.go new file mode 100644 index 0000000..d0a1327 --- /dev/null +++ b/days/2/day2.go @@ -0,0 +1,24 @@ +package _2 + +import ( + _ "embed" +) + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + + +func pickInput(useSampleInput bool) string { + if useSampleInput { + return sampleInput + } else { + return fullInput + } +} + +func Run(useSampleInput bool) { + pickInput(useSampleInput) +} diff --git a/days/2/input.txt b/days/2/input.txt new file mode 100644 index 0000000..7507561 --- /dev/null +++ b/days/2/input.txt @@ -0,0 +1,2500 @@ +C X +C X +C X +A Z +C X +C Z +C X +B Y +C X +C X +C X +B Y +C X +B Z +C Z +C X +C X +C Z +C Z +B Y +C Z +C X +B Z +C X +C X +C X +B Y +C Z +B Z +C X +B Y +C Z +A Y +C X +B Y +A Y +C X +C Y +C X +C Z +C X +C X +A Y +C X +C X +B Y +B Y +C X +C X +B Y +C Z +B Y +B Y +C X +C X +C Y +B X +C X +C X +B X +C Y +B X +B Y +C X +C Z +B Y +B Y +B Y +B X +C Z +C X +B Y +C X +A Y +C Z +A Y +C Z +C X +C Z +B Y +B X +C X +B Z +C X +C Y +C X +C X +C Z +C Z +C Z +B Z +C Y +B Y +B Y +B Y +C X +B Y +C Z +C X +C X +C X +B Y +C Z +C X +C X +C X +C X +C X +B Z +C X +A Y +B X +C X +C X +C X +A Y +B Z +C X +C Z +C X +A Y +C X +B Y +C Z +C X +C Z +B Z +B Y +B Y +C Z +B Y +B Y +B X +B Y +B Y +C X +C Z +C X +C X +C X +C X +C X +C X +C X +C X +C Z +C Y +B Y +B Y +C Z +A X +C X +C Z +B Z +B Y +C Z +C X +C X +B Z +B Z +C X +C X +C X +B X +A Y +B X +C X +C Z +C X +C Z +B Y +C X +B Y +A Y +A Y +A Y +B Y +C X +C Y +B Y +A Y +C Z +A X +C X +C Z +C X +C X +C X +C Z +C X +B X +A X +C Z +C X +C X +C Y +C X +C Z +B Y +C X +C X +C X +C Z +C X +B X +C X +B Y +B X +C Y +C X +C X +C Y +C X +C X +C X +C X +B Y +C X +B X +B Y +C Y +C X +C X +B X +C X +C X +B Y +A Y +C Z +C X +B Y +C X +C X +C Z +C X +C X +A Z +C X +C Y +A Z +C Z +C Z +B Y +C X +B Y +C X +C X +C X +B Y +B Z +C X +C X +C X +B X +B Y +C X +A Y +B X +B X +B Y +B Z +C X +B X +C Z +C X +B Y +C X +A X +C Y +A Z +C X +A Z +B Z +C X +B X +B Y +A Y +B X +C X +B Y +B X +C Z +B Y +B X +A X +C Z +B Y +C X +C X +C X +A Y +B Y +C X +B Y +C Z +C X +C Z +B Z +B X +A Y +C X +B Y +C X +C X +C X +B Y +B Y +B Z +B Y +C Z +C X +C Z +C X +C Z +C X +C X +A Y +C Z +B Y +A Y +B Z +C X +C X +C X +C X +B Y +C X +C X +C X +C X +A Y +C X +C X +C X +C Z +C X +B Y +C X +C X +C Z +C X +C X +C X +B Y +B Z +B Y +C X +C X +C X +B Y +C X +B Y +C X +C X +C Z +C Y +C Z +C Z +C X +C X +C Z +A Y +C Z +C X +B Z +C X +C Z +C X +C X +B Y +B Z +B Z +A Y +B Z +C Z +C X +C Y +B Y +A Y +C X +A Y +A Z +B Z +A Y +C X +C Z +A Y +B Y +B Y +C X +C Z +B Y +C X +C X +B Y +C X +C Z +B Y +B X +C Z +C X +C Y +C X +C X +C X +C Y +C X +B Z +C Y +B Y +B Y +C X +A Y +C X +A Z +A Y +B X +C X +B Y +C X +B Y +B Y +C Z +C Z +A Y +C X +A Y +C Z +C X +C Z +C X +B Y +B X +C X +B X +C X +C X +B Y +C X +C X +C X +C Z +C Z +B Y +C Y +C X +C X +B Y +C X +C Z +C X +C Z +C X +C Y +C X +C Y +C Z +C X +B Y +C X +B X +B Y +C Z +B Y +B Z +B Z +C X +A X +C X +C Z +C Y +C X +B X +C Y +A Y +C Y +C X +B Y +B Y +C X +C Z +B X +A Y +C X +C X +C X +B Y +B Y +B Z +C Z +C Z +B X +C X +B Z +C X +B Y +B Y +C Z +C X +C Z +C X +C X +C X +C Z +C Z +C Z +C X +B Y +C X +C X +B Y +C X +C X +C X +A Y +C Z +B Z +B Z +C Z +C X +C Y +C X +A Y +C X +C X +C Z +C X +B Y +B Y +C X +C Z +C Y +B X +B Y +A Y +B Y +C X +C X +C Z +B Y +C X +C Y +C Y +A Z +B Y +C X +B X +A Y +B Y +B Y +C Z +A X +C X +A Y +C Z +C Z +B X +A Y +C Y +B Y +C X +A Y +B Y +C X +C X +A Y +B Y +C Z +C X +C Z +A X +A Z +C X +C Z +C X +C Y +C X +B Y +C Z +C X +B Y +C Z +C X +B Z +B X +C X +C X +B X +C X +C Z +C X +C X +C X +C Y +B X +C X +C X +B Y +B Y +C X +B Y +C X +C Z +C X +B Y +B Y +B Y +C Z +C X +A Z +A Y +C X +C Z +C Z +A Z +B Y +A Z +C Z +B Z +B Y +C X +B Y +C X +B Y +A Y +C X +C X +C X +C X +B Y +A Z +B X +C X +C X +C X +C Z +B Y +C X +B Y +B Y +B Y +C X +C Y +B Z +C X +B Y +B X +C X +C X +B Y +C X +B X +C X +C X +A Z +C X +A Z +C X +C X +C Z +C X +B Y +C Z +B Y +C X +B Y +C Z +B X +C X +A Y +C Y +C X +C X +B Y +B Y +C X +C Z +C Z +C Z +C X +C X +B Z +B Z +A Z +B Y +B Y +B Y +A X +C X +B X +B X +C X +C X +C X +C X +B X +B X +B Y +B Y +B Y +B X +C X +C Z +B Y +B Y +A Y +A Y +C X +C X +C X +B X +C Z +C X +C X +B Y +C X +C X +C X +C X +B X +B X +A Y +B Z +C Z +B Z +A X +C X +B X +C X +B Z +C Z +B X +B Y +C Z +C Y +C X +C X +C Z +C X +C X +C X +C Z +C X +B Y +C X +C X +C X +A Z +C Z +C X +C X +C X +C Y +A Y +C Z +B X +B X +C X +C X +C Z +A Y +C Z +C X +B Y +B Y +B Z +B Y +C X +B X +C X +C X +B Y +C Y +C Z +C X +C Z +B Y +C Y +B Y +B X +C Y +B X +C X +C X +B Z +C Y +B Y +B Y +B Z +C Y +B X +B Y +C Z +A Y +B Y +B Y +A Z +C X +C Z +B Z +C X +C X +B Y +C X +C X +B X +C X +C Z +C Z +B Y +B X +B Z +B Z +B X +C X +C X +C X +C X +B Y +A Y +B X +C X +C X +C X +B Y +C Z +B X +C Y +C Z +B Z +C X +C X +B Y +C Z +B Y +C X +C X +B Y +B X +C X +C X +C X +C X +B Y +A Y +C Y +C X +C X +B Y +B X +B Y +C X +C X +C Z +C X +C Z +A Y +C X +C Z +B Y +C Z +B X +A X +C X +C Z +C Y +B Y +C X +C Z +C Z +B X +C X +C X +C Z +C X +A Y +B Y +C X +C X +C X +C X +C X +C X +B X +B X +C Z +B Y +C X +C X +A Z +C X +C Z +B Y +C Z +C Y +C X +C Y +C X +C X +C Z +B Y +B Y +B Z +B Y +C Z +C X +C Z +B Y +C Z +C X +C X +C X +C Y +C X +C X +B X +C X +B Y +B X +B X +B Y +B Y +B Z +C Z +A Y +B X +B Y +C Z +C Y +C X +C X +C Z +A Y +C X +C Z +C X +B X +B Z +C Z +B Y +C X +C X +C Z +B X +B Y +C Z +B Z +B Z +C X +C X +C X +B Y +C X +C Z +C X +C X +B Y +C X +B Y +B Y +C X +C X +C X +B Y +B Z +C X +C X +B X +B Y +C X +C Y +B Y +A Y +C X +C X +C X +C Y +C X +C Z +A Y +B X +C Z +C X +C X +C X +B Y +B Y +C Z +C Z +C Y +C Z +C X +B Y +B Y +C X +B Y +C X +B Y +C X +C X +C X +C X +C Z +B Y +B Z +C X +C X +B Y +C X +B Y +C X +B Y +C Y +B Y +C X +B Y +C X +B Y +C X +B Z +C X +B X +B X +B Y +B X +B Z +C X +B Y +C X +B Z +B Y +C X +C Y +C Z +A Z +C X +C X +B Y +A X +C X +B Z +C Z +B X +C X +C X +B Y +B Z +A Z +A Z +C X +C X +C X +C X +A Y +B Y +B Y +C X +B Z +C Z +C X +C X +B Z +C Z +B Y +C Z +C Y +C Z +B Y +C Z +B Z +B Y +C X +C Z +C X +C X +C Y +C X +B X +A X +B X +C X +C Z +C Z +C Z +B Y +B X +C X +B Y +C X +C X +C X +A Y +C Z +A Y +C X +C X +C X +B Z +C X +C Z +C X +B Y +B Y +B X +C X +C Z +C Z +A Z +B Y +C Y +B Y +C Z +C X +A Z +C X +B X +B Z +C X +B Y +C Y +C X +B X +C Z +C Z +C Z +C X +C X +C X +A Y +C Z +B X +B X +B Y +B X +A Y +C X +B Y +C X +C X +C X +B X +A X +B Y +C X +C Z +B X +A X +C X +B Y +C X +C Z +A X +C X +B Z +C X +C Z +C Z +B Z +C Z +C X +B Y +C X +B Y +C Y +B Y +C Y +B Y +C X +B X +C Y +C X +C X +B Y +C Y +A Z +C X +C X +C X +C X +B Y +B Y +C X +C Z +C X +C X +C X +B Y +B Y +B Y +C X +B Y +B X +C Y +B Y +C X +C X +B Y +C X +C Y +C X +B Y +C X +B Y +C Z +C X +C X +C Z +C Z +B Z +C Z +C X +C X +C Z +C Z +B X +C Y +C Y +C X +C X +B Z +C Z +B Y +B Y +C Z +C X +C X +B Y +C X +C X +C Z +C X +C Z +A Z +B Y +C Z +C X +A X +A Z +B Y +B Y +B Y +B Y +C Z +B X +C X +B Y +B Y +C X +B Y +B Y +C Z +C X +B Y +C Y +C X +C Z +C X +A Y +C X +C X +C Z +A X +B Y +B Y +B Z +B Y +C Z +C X +C X +B Y +C X +C Z +C Z +C X +B X +C Z +C Z +B Y +B Y +C X +B Y +B X +C X +A Y +B Y +B Y +C X +C Z +B X +C X +C Z +A Z +B Y +C X +C Z +C X +C X +C X +B Y +B X +B Y +B X +C X +C X +C Z +C X +C X +C X +C X +B Y +C X +B Y +C Z +B X +C Z +C X +B Z +C X +A Y +C X +C X +C X +C X +C X +C X +B Y +C X +C X +B Y +C Z +C Z +B X +C X +A X +C X +C X +B X +C Z +B Y +B X +C X +C X +B Y +C Z +C Y +B Y +C Y +B X +C X +B Y +C X +C Z +C Z +B Y +B Y +A Z +B X +C X +C X +C Z +C X +C X +B X +C Z +A Y +C Z +C X +C Z +C X +C Z +C Z +A Z +A Y +A Y +C Z +C X +A X +C X +B Y +B Y +C X +C Z +B X +B Z +C X +C Z +B Y +C Z +B Y +C Z +B Z +B Y +C X +C X +B Y +C X +C X +C Z +B X +C Z +C Z +B Y +A Z +C X +B Y +C X +C Z +C X +C X +B Y +C Z +A Z +C X +C X +B X +C X +C X +B Z +B Y +B Y +B X +C Y +C X +B Y +B Y +C X +C X +C X +A Z +C Z +A Y +C X +B Y +B Y +C X +C Z +C X +C X +B X +B Y +C Z +B Z +C Y +C X +C X +B Z +B X +C Z +C X +C X +C X +C X +C X +C X +C X +C X +B Y +C Y +C X +B Y +B Y +B Y +C X +C X +B X +C Y +B Y +C X +B Z +C X +C X +B Z +C Z +B X +B Z +C Z +B Z +C X +B Y +C X +C Y +A Y +B X +B Y +B Z +C X +B Z +A Y +C Z +C Z +C Y +B Y +B Y +B Z +C X +C X +A Y +C Z +C X +C X +C X +C Z +C X +C X +C X +C X +A Y +C X +C Z +C Z +C X +B Z +C X +C X +A Y +B Z +C Y +A X +C X +C X +C Z +C X +C X +C X +A Y +A Y +C Z +B Z +B X +C X +C X +C X +A Z +B Y +C Z +C Z +C X +C X +C Z +C X +B Y +B X +C Z +C X +B Y +B Z +C X +C X +B Y +C Z +C Z +C X +B Y +C X +C X +B Y +A Z +B X +C X +C X +C X +B Y +C X +C Z +B Y +B X +C Z +B Y +B X +C X +C X +A Y +C Z +C X +C X +C Z +B Z +B Y +B Y +B Z +C X +A Y +B X +C X +C X +B Y +C X +C Z +B Y +C X +C X +C X +C Y +B Y +B X +B Y +C X +C X +C Z +C Z +A Y +C X +C Y +B Y +B Y +B X +C X +C X +B X +C X +C X +C X +B X +C X +C Z +C X +A X +B Y +C Z +B Y +C Z +C X +C Z +C X +B Y +C X +B X +A X +A Z +C X +C Z +C X +C X +B Y +B X +B X +B Y +B Z +C Z +C X +C Z +B X +C X +B Y +B X +B Y +B Y +C Y +C X +B X +B Y +C X +C Z +C X +B Y +C X +C X +B Y +C X +C X +C Z +C X +B Z +A X +C X +C X +B X +C Y +C X +B Y +C X +C X +A Y +A X +C X +B Z +C X +A X +C X +C Y +C X +C X +C X +C Y +C X +C X +B Z +C X +C X +B X +B X +C X +C X +B Z +C X +A Y +B X +B Y +C X +C X +B X +B Y +C Z +B X +B Y +C X +C X +C X +C Z +C X +C X +C X +A Y +A Z +C Z +A Y +B Y +B Y +C Y +C X +C Y +C X +B Y +C X +C Z +A Y +B X +C Z +B Z +C Z +A Z +A X +B Y +B Y +C X +C Y +B Y +B Y +B Y +C Y +C X +B Y +B Y +C X +C X +B Y +C X +B Y +B Y +C Y +C Y +A Y +B Y +B Y +C X +B X +B X +C X +B Y +A X +C Z +C Z +C X +A X +B Y +C Y +B Y +C Z +C Z +B Y +B X +B Y +B X +B X +C Y +C Y +B Z +B Y +C X +C X +C Y +C X +C X +C X +C Z +B Y +B Y +C X +C X +C Z +B Y +A Y +B Y +B Y +B X +C X +C Z +C X +C Z +C X +B Z +C Z +C X +B Y +A Y +C X +A Y +B Y +C Y +A X +C X +B Z +C X +B Y +A Z +C X +C Z +C Z +C X +A Y +C Z +C X +C X +B Y +C Z +B Z +B Y +B Y +C Z +A Y +C X +B X +C Z +C X +B Y +A Y +B Y +B Y +C X +C Y +B Z +B Y +B X +C Z +C X +C X +B Y +A Y +B Y +C X +C X +B Y +B Y +C X +C Z +C X +B Y +C X +B Y +B Y +C X +C Z +A Z +B X +C Z +B X +C X +C Z +B Y +B Z +C X +B Y +C Z +C X +C X +C X +B Z +C X +C Z +C X +C X +B Y +B Y +C X +A X +A X +C X +C X +B X +C X +C Z +B Y +C Z +C Z +C X +A Y +A Z +C X +C X +B Y +B Y +B Y +C Z +B Y +C X +C X +C X +B X +B Y +B X +B Y +A Y +C X +B X +C X +C Y +C Z +C Y +C Z +C X +A Y +C X +B Y +C Z +C Z +C X +B Y +B Y +B Y +C X +A X +C X +B X +C Y +C X +B Y +C Z +C X +C Z +C Z +C Z +A Y +B Y +B Y +C X +A Y +C Y +B Y +C X +B Z +B Y +C X +B Y +C Z +B Y +C Z +C X +B Z +C Z +C Z +B X +C X +C Y +B X +B Y +C X +A X +B Y +C Z +B Y +C X +C X +B X +C X +B Y +C X +B Y +C Z +C Z +C X +C X +A Y +B Y +C Y +B Y +B Y +B Y +C X +C Y +A X +A Y +C X +C X +B X +B Y +C X +C Z +C X +B Y +C X +C Y +B Z +B X +C X +A Y +C X +C Y +C Z +B X +C X +C Z +C Y +C X +C Z +C X +C Z +B Y +B Z +C X +A Y +C X +C X +B X +B Y +C X +C X +B Y +C X +B Z +C X +C X +C X +B Z +A Y +B X +B Y +B Y +B Y +B Y +C X +C Z +B Z +C Z +C X +B Y +C X +B Y +A Y +C Y +B X +B Z +C X +C X +C X +A Y +B X +B Z +C X +C Z +B Y +C Z +C X +B Y +B Z +C Y +C Y +C X +C X +B Z +B Y +A Y +C Z +B Y +B Y +A Z +C X +B Y +A Y +C X +C Z +B Y +C X +A Z +C X +B Z +B Y +C Z +B Y +C X +B X +B Y +C X +B Y +C X +C Y +B Y +B X +C X +C Y +C X +B Y +C Y +C X +C X +B Y +B Y +B X +C X +B X +A Y +C X +B Y +C Y +C Z +C X +B Z +B X +C X +C X +C Z +C Z +B Y +C X +C X +B Y +C X +C X +A Y +C Z +C X +A X +B Y +C X +C X +C X +C Z +B Y +C X +B Y +B Z +C X +C X +B Y +A Z +C X +C X +C X +A Y +B Y +C X +C Y +C Z +A X +C X +C X +B X +B Y +C X +B Y +B X +B X +C X +C Z +B Y +B Y +C Z +B Y +A Y +C X +B Y +C X +C Z +C X +C Z +A Y +C X +B Z +C Z +B Z +C Z +C X +B Y +A Z +C X +C Z +B Y +B Y +C X +C Z +A X +B X +B Y +C X +C X +B Z +C X +C X +C Z +A Y +C X +A X +C X +C X +B X +C Z +B Y +B Y +C Z +B Y +B Y +C X +C X +B Z +B Y +B Y +C X +A X +C X +B Y +C X +B Y +C Z +A Z +C X +C Z +C Y +B Y +C X +C Z +C Z +B Y +B Z +B X +C Z +C Z +B Z +B Z +B Y +C X +B Y +B Y +B X +B Y +C X +C Z +C Z +B Y +B Y +B Z +C X +C Z +C Z +C Z +C X +C X +B Y +C X +B Y +B Y +C Y +C X +B Y +C X +C X +C X +C Z +A Z +C X +A X +A Y +B Y +C X +B Y +B Y +C Y +C X +C X +C X +B Y +C X +A Y +B Y +C Z +C Z +C X +A Y +C X +B Y +C X +C Z +C Z +C Y +B Y +C X +B Y +B Y +C Y +C X +B X +C Z +C X +C X +C X +B Y +B Z +C Z +C X +C Z +B Y +A Z +C X +C Z +B Z +A Z +B Y +B Y +C X +C Z +C X +C X +C X +C X +C Z +C X +B Y +C Y +B Y +C X +C Z +B Z +B X +C Y +C X +B Y +C X +B X +C X +C X +C Z +C X +B Y +C X +C Z +C Z +B X +C X +B Y +C X +B Y +B X +C X +A Y +C X +C X +C Z +B Y +C X +B Z +C X +C X +C X +C X +B Z +C X +B Y +C X +B X +C Z +C X +B Y +C X +C X +C X +A Y +B Z +C Z +A Z +C X +B X +C Z +C Y +B Z +C X +B Y +B Z +C X +C Z +B X +C X +C Z +C X +B Y +B X +B Y +B Y +C Y +C Y +C Y +C X +B Y +B Y +C X +C X +C Y +B Y +C X +C X +C Z +C X +B X +C X +C Y +C X +C X +C X +C Z +C Z +C Y +C Z +C Z +B X +C X +C X +B Y +C X +C X +C Z +B Y +C X +C X +C X +A Y +A X +C Z +C Z +C X +C X +B X +B Y +C X +C Y +B Y +B Y +C X +C Z +C X +C Z +B X +C X +C X +B Y +B Y +B Y +C X +C X +C X +C Z +C X +C X +B Z +C X +C Y +C X +A Y +C X +C X +B X +C X +C X +B Z +C X +C X +C Z +C Z +C X +C Y +C X +C X +C X +C X +B Y +C X +C Y +C Z +C X +C X +C X +C X +B Y +B X +C X +C X +C Y +C X +B Y +C X +C X +C Z +C Z +C X diff --git a/days/2/sample.txt b/days/2/sample.txt new file mode 100644 index 0000000..db60e36 --- /dev/null +++ b/days/2/sample.txt @@ -0,0 +1,3 @@ +A Y +B X +C Z From f2ec62d459c4041c064c5e0eb44e2049714f9be3 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 2 Dec 2022 09:32:22 +0100 Subject: [PATCH 007/120] Add a run configuration for full and sample for easy switching --- .vscode/launch.json | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 7c239fe..6e67938 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,12 +5,23 @@ "version": "0.2.0", "configurations": [ { - "name": "Day 1", + "name": "Sample", "type": "go", "mode": "debug", "request": "launch", "args": [ - "day1", + "day2", + "--sample=true" + ], + "program": "${workspaceFolder}" + }, + { + "name": "Full", + "type": "go", + "mode": "debug", + "request": "launch", + "args": [ + "day2", "--sample=false" ], "program": "${workspaceFolder}" From df886d2970fa487d4c53fd582bbe4efa95efedf7 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 2 Dec 2022 09:32:40 +0100 Subject: [PATCH 008/120] Day 2, Task 1: Kiss! --- days/2/day2.go | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/days/2/day2.go b/days/2/day2.go index d0a1327..31204b5 100644 --- a/days/2/day2.go +++ b/days/2/day2.go @@ -2,6 +2,8 @@ package _2 import ( _ "embed" + "fmt" + "strings" ) //go:embed sample.txt @@ -10,7 +12,6 @@ var sampleInput string //go:embed input.txt var fullInput string - func pickInput(useSampleInput bool) string { if useSampleInput { return sampleInput @@ -19,6 +20,37 @@ func pickInput(useSampleInput bool) string { } } +var roundValue = map[string]int{ + "A X": 3 + 1, + "A Y": 6 + 2, + "A Z": 0 + 3, + "B X": 0 + 1, + "B Y": 3 + 2, + "B Z": 6 + 3, + "C X": 6 + 1, + "C Y": 0 + 2, + "C Z": 3 + 3, +} + +func simulateGame(rounds []string) (int, error) { + var score int + for _, round := range rounds { + if round == "" { + continue + } + + score += roundValue[round] + } + return score, nil +} + func Run(useSampleInput bool) { - pickInput(useSampleInput) + input := pickInput(useSampleInput) + + rounds := strings.Split(input, "\n") + score, err := simulateGame(rounds) + if err != nil { + panic(err) + } + fmt.Printf("Score according to guide: %d\n", score) } From 888b768a80cf69043af5ca718c917ffe23ac8f4c Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 2 Dec 2022 09:38:52 +0100 Subject: [PATCH 009/120] Update .editorconfig to better match `go fmt` indentation --- .editorconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.editorconfig b/.editorconfig index 0385e34..7a952c1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,8 @@ root = true [*] end_of_line = lf insert_final_newline = true + +[*.go] +end_of_line = lf +insert_final_newline = true +indent_style = tab From bdbac03668c5026eff07aec79829e7dae54bc696 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 2 Dec 2022 09:39:15 +0100 Subject: [PATCH 010/120] Run `go fmt` --- cmd/root.go | 2 - days/1/day1.go | 134 ++++++++++++++++++++++++------------------------- days/2/day2.go | 62 +++++++++++------------ 3 files changed, 98 insertions(+), 100 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 2cadb0a..1545cbb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -26,5 +26,3 @@ func Execute() { func init() { rootCmd.PersistentFlags().BoolVar(&useSampleInput, "sample", true, "Use the sample input for the day") } - - diff --git a/days/1/day1.go b/days/1/day1.go index 2b351fa..e5f3583 100644 --- a/days/1/day1.go +++ b/days/1/day1.go @@ -15,90 +15,90 @@ var sampleInput string var fullInput string type topN struct { - data []int + data []int } func makeTopN(n int) topN { - data := make([]int, 0, n) - return topN{data} + data := make([]int, 0, n) + return topN{data} } // Insert inserts the given value if it fits (i.e. either there is capacity left, or it is bigger than at least one existing value). func (t *topN) Insert(v int) bool { - l := len(t.data) - - // Find the insert point - at := sort.Search(l, func(i int) bool { return v >= t.data[i] }) - - // No space to add it, and not big enough to shift something out. - if at == cap(t.data) { - return false - } - - // We might not be using all of the capacity yet, expand the array - dropAtEnd := 1 - if l < cap(t.data) { - t.data = append(t.data, 0) - dropAtEnd = 0 - } - - // Shift things if the insert point is not at the end - shiftLen := l - at - dropAtEnd - if shiftLen > 0 { - copy(t.data[at+1:at+1+shiftLen], t.data[at:at+shiftLen]) - } - t.data[at] = v - return true + l := len(t.data) + + // Find the insert point + at := sort.Search(l, func(i int) bool { return v >= t.data[i] }) + + // No space to add it, and not big enough to shift something out. + if at == cap(t.data) { + return false + } + + // We might not be using all of the capacity yet, expand the array + dropAtEnd := 1 + if l < cap(t.data) { + t.data = append(t.data, 0) + dropAtEnd = 0 + } + + // Shift things if the insert point is not at the end + shiftLen := l - at - dropAtEnd + if shiftLen > 0 { + copy(t.data[at+1:at+1+shiftLen], t.data[at:at+shiftLen]) + } + t.data[at] = v + return true } func (t *topN) Iterate() []int { - return t.data + return t.data } func findHighestCaloriesOnElf(input string, n int) (int, error) { - topN := makeTopN(n) - - var current int - for _, line := range strings.Split(input, "\n") { - if line == "" { - topN.Insert(current) - current = 0 - } else { - calories, err := strconv.ParseInt(line, 0, 0) - if err != nil { - return 0, err - } - current += int(calories) - } - } - - result := 0 - for _, calories := range topN.Iterate() { - result += calories - } - return result, nil + topN := makeTopN(n) + + var current int + for _, line := range strings.Split(input, "\n") { + if line == "" { + topN.Insert(current) + current = 0 + } else { + calories, err := strconv.ParseInt(line, 0, 0) + if err != nil { + return 0, err + } + current += int(calories) + } + } + + result := 0 + for _, calories := range topN.Iterate() { + result += calories + } + return result, nil } func pickInput(useSampleInput bool) string { - if useSampleInput { - return sampleInput - } else { - return fullInput - } + if useSampleInput { + return sampleInput + } else { + return fullInput + } } func Run(useSampleInput bool) { - input := pickInput(useSampleInput) - - highest, err := findHighestCaloriesOnElf(input, 1) - if err != nil { - panic(err) - } - fmt.Printf("Highest calorie count on an elf: %d\n", highest) - - highest3, err := findHighestCaloriesOnElf(input, 3) - if err != nil { - panic(err) - } - fmt.Printf("Sum of the 3 highest calorie counts on an elf: %d\n", highest3) + input := pickInput(useSampleInput) + + highest, err := findHighestCaloriesOnElf(input, 1) + if err != nil { + panic(err) + } + fmt.Printf("Highest calorie count on an elf: %d\n", highest) + + highest3, err := findHighestCaloriesOnElf(input, 3) + if err != nil { + panic(err) + } + fmt.Printf("Sum of the 3 highest calorie counts on an elf: %d\n", highest3) } diff --git a/days/2/day2.go b/days/2/day2.go index 31204b5..ab59295 100644 --- a/days/2/day2.go +++ b/days/2/day2.go @@ -13,44 +13,44 @@ var sampleInput string var fullInput string func pickInput(useSampleInput bool) string { - if useSampleInput { - return sampleInput - } else { - return fullInput - } + if useSampleInput { + return sampleInput + } else { + return fullInput + } } var roundValue = map[string]int{ - "A X": 3 + 1, - "A Y": 6 + 2, - "A Z": 0 + 3, - "B X": 0 + 1, - "B Y": 3 + 2, - "B Z": 6 + 3, - "C X": 6 + 1, - "C Y": 0 + 2, - "C Z": 3 + 3, + "A X": 3 + 1, + "A Y": 6 + 2, + "A Z": 0 + 3, + "B X": 0 + 1, + "B Y": 3 + 2, + "B Z": 6 + 3, + "C X": 6 + 1, + "C Y": 0 + 2, + "C Z": 3 + 3, } func simulateGame(rounds []string) (int, error) { - var score int - for _, round := range rounds { - if round == "" { - continue - } - - score += roundValue[round] - } - return score, nil + var score int + for _, round := range rounds { + if round == "" { + continue + } + + score += roundValue[round] + } + return score, nil } func Run(useSampleInput bool) { - input := pickInput(useSampleInput) - - rounds := strings.Split(input, "\n") - score, err := simulateGame(rounds) - if err != nil { - panic(err) - } - fmt.Printf("Score according to guide: %d\n", score) + input := pickInput(useSampleInput) + + rounds := strings.Split(input, "\n") + score, err := simulateGame(rounds) + if err != nil { + panic(err) + } + fmt.Printf("Score according to guide: %d\n", score) } From 7581d741a70902bfb2724cfe4d51d0ddbb32b3d4 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 2 Dec 2022 09:51:37 +0100 Subject: [PATCH 011/120] Day 2, Task 2: Parameterization While there: Use enums to make things a bit more readable. --- days/2/day2.go | 62 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/days/2/day2.go b/days/2/day2.go index ab59295..985e7d6 100644 --- a/days/2/day2.go +++ b/days/2/day2.go @@ -20,19 +20,47 @@ func pickInput(useSampleInput bool) string { } } -var roundValue = map[string]int{ - "A X": 3 + 1, - "A Y": 6 + 2, - "A Z": 0 + 3, - "B X": 0 + 1, - "B Y": 3 + 2, - "B Z": 6 + 3, - "C X": 6 + 1, - "C Y": 0 + 2, - "C Z": 3 + 3, +type shape int + +const ( + Rock shape = 1 + Paper shape = 2 + Scissors shape = 3 +) + +type outcome int + +const ( + Lose outcome = 0 + Draw outcome = 3 + Win outcome = 6 +) + +var roundValueSimpleTheory = map[string]int{ + "A X": int(Draw) + int(Rock), + "A Y": int(Win) + int(Paper), + "A Z": int(Lose) + int(Scissors), + "B X": int(Lose) + int(Rock), + "B Y": int(Draw) + int(Paper), + "B Z": int(Win) + int(Scissors), + "C X": int(Win) + int(Rock), + "C Y": int(Lose) + int(Paper), + "C Z": int(Draw) + int(Scissors), +} + +var roundValueActualMeaning = map[string]int{ + "A X": int(Lose) + int(Scissors), + "A Y": int(Draw) + int(Rock), + "A Z": int(Win) + int(Paper), + "B X": int(Lose) + int(Rock), + "B Y": int(Draw) + int(Paper), + "B Z": int(Win) + int(Scissors), + "C X": int(Lose) + int(Paper), + "C Y": int(Draw) + int(Scissors), + "C Z": int(Win) + int(Rock), } -func simulateGame(rounds []string) (int, error) { +func simulateGame(rounds []string, roundValue map[string]int) (int, error) { var score int for _, round := range rounds { if round == "" { @@ -46,11 +74,17 @@ func simulateGame(rounds []string) (int, error) { func Run(useSampleInput bool) { input := pickInput(useSampleInput) - rounds := strings.Split(input, "\n") - score, err := simulateGame(rounds) + + assumedScore, err := simulateGame(rounds, roundValueSimpleTheory) + if err != nil { + panic(err) + } + fmt.Printf("Score according to theory about guide: %d\n", assumedScore) + + actualScore, err := simulateGame(rounds, roundValueActualMeaning) if err != nil { panic(err) } - fmt.Printf("Score according to guide: %d\n", score) + fmt.Printf("Score according to actual meaning of guide: %d\n", actualScore) } From 22909facc27b27a0164886d41e1169af9d56934e Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 2 Dec 2022 09:57:11 +0100 Subject: [PATCH 012/120] Remove a pointless `editor.insertSpaces` We're indenting with tabs here, and that is what .editorconfig and `go fmt` enforce. --- .vscode/settings.json | 1 - 1 file changed, 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2ee1498..04d1aba 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,7 +2,6 @@ "editor.formatOnSave": true, "editor.formatOnSaveMode": "modificationsIfAvailable", "[go]": { - "editor.insertSpaces": true, "editor.defaultFormatter": "golang.go" }, } From 75b98b0ace3e2e8ea5e085b5e25277e4b68d7493 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 4 Dec 2022 12:01:25 +0100 Subject: [PATCH 013/120] Day 3, Task 1: No concerns, yet. ... which is somewhat concerning, as this is a weekend task :) --- .vscode/launch.json | 4 +- cmd/days.go | 10 ++ days/3/day3.go | 62 +++++++++ days/3/input.txt | 300 ++++++++++++++++++++++++++++++++++++++++++++ days/3/sample.txt | 6 + 5 files changed, 380 insertions(+), 2 deletions(-) create mode 100644 days/3/day3.go create mode 100644 days/3/input.txt create mode 100644 days/3/sample.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index 6e67938..45761d3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "mode": "debug", "request": "launch", "args": [ - "day2", + "day3", "--sample=true" ], "program": "${workspaceFolder}" @@ -21,7 +21,7 @@ "mode": "debug", "request": "launch", "args": [ - "day2", + "day3", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index 7b93b79..c741c6a 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -3,6 +3,7 @@ package cmd import ( day1 "github.com/ankon/adventofcode/2022/days/1" day2 "github.com/ankon/adventofcode/2022/days/2" + day3 "github.com/ankon/adventofcode/2022/days/3" "github.com/spf13/cobra" ) @@ -23,7 +24,16 @@ var day2Cmd = &cobra.Command{ }, } +var day3Cmd = &cobra.Command{ + Use: "day3", + Short: "Rucksack Reorganization", + Run: func(cmd *cobra.Command, args []string) { + day3.Run(useSampleInput) + }, +} + func init() { rootCmd.AddCommand(day1Cmd) rootCmd.AddCommand(day2Cmd) + rootCmd.AddCommand(day3Cmd) } diff --git a/days/3/day3.go b/days/3/day3.go new file mode 100644 index 0000000..1d6c372 --- /dev/null +++ b/days/3/day3.go @@ -0,0 +1,62 @@ +package _3 + +import ( + _ "embed" + "fmt" + "strings" + "unicode" +) + +func findCommonItem(compartment1, compartment2 string) (rune, error) { + for _, c := range compartment2 { + if strings.ContainsRune(compartment1, c) { + return c, nil + } + } + return -1, fmt.Errorf("no common item") +} + +func calculatePrioritySum(rucksacks []string) (int, error) { + var sum int + for _, rucksack := range rucksacks { + if rucksack == "" { + continue + } + l := len(rucksack) + compartment1, compartment2 := rucksack[0:l/2], rucksack[l/2:] + commonItem, err := findCommonItem(compartment1, compartment2) + if err != nil { + return 0, fmt.Errorf("cannot find common item for %q: %w", rucksack, err) + } + if unicode.IsUpper(commonItem) { + sum += int(commonItem - 'A') + 27 + } else { + sum += int(commonItem - 'a') + 1 + } + } + return sum, nil +} + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +func pickInput(useSampleInput bool) string { + if useSampleInput { + return sampleInput + } else { + return fullInput + } +} + +func Run(useSampleInput bool) { + input := pickInput(useSampleInput) + rucksacks := strings.Split(input, "\n") + prioritySum, err := calculatePrioritySum(rucksacks) + if err != nil { + panic(err) + } + fmt.Printf("Sum of priorities: %d\n", prioritySum) +} diff --git a/days/3/input.txt b/days/3/input.txt new file mode 100644 index 0000000..cd857ef --- /dev/null +++ b/days/3/input.txt @@ -0,0 +1,300 @@ +jNNBMTNzvTqhQLhQLMQL +VCwnVRCGHHJTdsLtrdhrGdsq +wFJZTbRcnJCbpwpFccZCBfBvPzfpgfgzzWvjSzNP +wDWgDfWNTvwvgFfWfddGldJVprrrVdNlrN +nLnmLSnmMVJvSrHqdV +MsmsbLvtzMjFsCPDsfBwwT +WTqSCqWSWqSgVZqJHpHmHrhMMVrRhBnn +PtLGLGddGGMCpprM +jFvLPPlLjvfjjffsclvPqzzJWTbqNSWZsbSTDzCW +lLSSrfmddlNpnmLdfSPddDdbZQTZgZjbZgjcQZHQPjQgZP +MJMnhzBJVJwvGsMRhRhTsHTjZjHFctbtHZcgZj +vzvBWGJMVGwWGGhGqVBnGzVGDfCDmrqNfrrLSdpSfLSpNmNC +qGWLgfbWhqpLgZbJvTRWJTvMWRslMv +FQwPwNPCVFQQdNcFHNcwwsvslRDRTMDMsVTGJGtRTs +wQHnwnQFPNPdjnnPjhphGqBrfpBBBfZf +mpVpmtPhVtPBLLbQTJpBLZ +vzFMlMzvvRZMTbJQJQbf +srqzvRRqdvzFFrDnvqldFVtwCVCHWNqJHNNcHchCPt +CQJJLZCJLqNMMDDgGLVV +RfRFFszTtzbWTFnRtFrRrWvNHghvBVGgMffvmBVDNgGV +znsjWzstnWjbDnDbTZCpwZcjpjZqQCwSPp +jRrzzrPjLnnpQQDsjj +CTVnTlZWHTcqZBcTTTHqWscQsQDQQDsmmQfvfhwDmv +qlWFWWHTZTlqTFWZHtBVFdlTGdNzRnNngbbSrrSNNzPgPGSz +cWjbcjnssMmRPWbGsWcMbfLBFrZBBLLgZwBrlfLQZtCw +vqpvFHNvhvJzdZQZtlgNNwlrrw +JzqVVVVpzhVJqzhSzJhhDVnFjRRMsPnSRcGMRMjWjWmR +NznNGQgSRQffbbsR +jjjCLwdvLcrhqdblFJsFSPfbDP +qrrvwHqjtLmSSggpBtgn +LGPtFtTfTfTfLrrWTSWGPrrsszbsjZHzgdzSwzbHdsglwl +NhHpVpqNNqbdszRRRb +ccBMJVDNCvvhDNpvNDpnNCVCHFPTmfLTGPMQrfLGmMLWWQQL +dRgRhVLRlncZSSrtLp +WJmwvvvjQvWwFBBvFJPHpwvGWTScGsrZtttGTSsrzTsSZt +FFHJjmjjjPMvfHfwpdRqMppghdRCddDg +NDTRFSnNsVVBDVlM +JjLZWqwjHvfrvmHHvjLWWLlhPlnPlChlQhJQnnzPPBCV +mwHvHmpvwpLmjnvpvLvvNGcTTggRbdTGcbNbTTpS +GGhZQMsmGRfMwfpclgdBlbblBBZgJc +tFvFSTSDnDTTLtcFMbWcBgclJrgd +vzDtzMVtnLTTMTSjSDHtppqhsqqfGjmpPhmsRGPG +MfJtWTTMJfzBbVWPZWQbNnDV +FvlgSHSLvmCvZjgcCQQsPQQsjnbVDNVsdn +HLhclRlHRmHvmLmclLZFSFwRRRpJMtwJwfGGrrtrwfpf +scsswLQcGmQmNHCqvrsHqfff +bdnPSMMMClbBBPCdDDnDVMDWWWvfvWFfFJfNqqNVFqFNfr +bDPTlSTPPbSPjnPSbGmQLCcjLjwzRLcmCG +tFFJjMnFhdcMMJlWtdnlFczBSZGNSjGGbBGZLbZZbLGB +QRgqwwvsLssZnGCz +gqfvvnpfHwRmHTFdFcPdJJmJJc +fccTzVVcfSmdThTTFJPFgg +wLsWfppsjBrnnwjCBZnZqJJQGhBdFJddQhFqdQBG +pZrNCWLwLZLjwwWMftmNzttDcVzVvt +rZnVVjVSMcrwsNbc +dLvQLBLFddvBLzpGmddQCqNswzsMjbhgbblbcwshlb +LLCCWjGBFPmCWdmmPWLdWBpLRZDSPRnHSStRfnZnZTnSSTfJ +ddfnQRbpldRlRLgFglqGCLqsGq +BWBVDZWTBTDPvVTZVDBDNMbhcLLHsFqgvHJsLCJCGcHGsJLH +NPZPDMWZMbZrBVMDDWNmBhMVpSSRpzjjfjpwRnSpwzRzdzjr +bvPSBttgGmZwScwShS +NJspjJLdprzHgjrLzLNrnHQCmmcZQWlcQcNQwlwcQCZC +HdRJsJrdHTbqGMDtgDqT +sNVvSdTstDCtdzdzSCwTzCRhRQjfclMflppjGhffjZcN +rgWlrnLLbqbQMfMphpWjjf +BmrnrFPnnBLlqVwDCtCtVPDTzT +mJMqlVlttQlFVmzFQMQMbQMSSDNwwdSddNddwdDswRDVdR +GGZgcfjrvCCZvgCZqvPHSwRBBsBwswcwBNTDTcSR +GZppfGHGrgGprZhLthFJhFqLWWFhtq +WDHHLtRBHgDnVrWFVFBTdzzZLLjZzjjvddLsvv +JlqmMpCMCGMwbwZddTtCtv +cJJqSplpfSGccJGthFVcVHgFBWBgHgDB +tlFwbWtQFLJhlBFlWPbwmsQndTrrqdnggjqdgnTgTT +GCMBDDCvRpDVpRpHrsgdqTjqgdHcsjHd +MDDvCVGzBGfpzBSNMSRRmwbLWlPmzbPmlJlWbFbJ +fzFzFHBfnvpHFbnzbHfBHZggCGgtZCltDGggdCCVtZVD +sLMNSccQLMSrmLcshLvtCGllPtDdGgtJgmlV +cwLMwwNhQhsWSjqTqHnHbjWTvH +NWlqqhNNnGtNvvWQdrVGBBQdVrwRQr +mppCjppMrDTSgDppCDTMQVRwdBbBQVVbQdQsVB +pgzzTFFFrjHqHnqJFWnh +ncQrhQjqjVQhGsGBbhtsstTp +RllWFLRfZrGlBTbg +vFLLmfNRFSNDfSNjcwqJVrVVzQjc +mmGrgwmGDGcVWVjNNW +nDsqfPCHnpntDssfJPDPjWWhjNTTcjjhTTNcqWcc +DfPCJLpbldRrlrdwmw +dJDNbRhNbJdhqCnrWjhsTWvplg +LMHrttLFcMmcMFLmtGplCggpjjnvTpgnTTFT +czZMzrzVZzHZdNdbDDqDVQNR +sbsJgbsmzdgRgWdg +LLLFBzGMLjzzFtVFwwwCPPRCCqQQTnnCMMCMCC +GllfptwjLjlGFVFjGzpFFNbJDmprrNDsDmDvJhmcvp +SccPbfbncpcfsjbRjMBCTTFGMTCQtJtzFFFJ +vvvdgVhlmlwlgZLgmJhWQCWGGbWtWJhzTJ +NbLNDdbLVmqqmfcsrHcrpPqrcH +HcgDBJSHTCzjjnMNJjrW +VppGMwFwllwwbZZrjvnqmzmnzpqjNv +wZlhtPGPLFVFlGZbVtVTQLLBQRRTSHTSMDCgLs +HPMMnhBHlMnMBPBHJHPWfdnBmjvLZvjTvZTZDgTgTmQmZhZZ +SrzrSScrctrwVzCSCmzQjmLTLvGDvTjGbm +CswstFRNpcwVNRrVVSVwpwpHJnnWWBBHfWHlffWfQMnM +mlFMtqjvMdqjmMCCJZsRQBnszlZz +HcNgcPLcHLwtcfZBTsnsHJBJTzCQ +LGGNhbNtNLDfcgcwfbgthfwFrqqVdFMqMMhMmvShFqmvVv +NbvbBGNvhNhnhpbgpGfBvNgmRjCdPCPCCRCQmmpRdTmTPR +qqFSSqWrtSSccjMdQMHFMBjPMj +SBDSBZZZwGGZNJJg +qTdHSLSFRZRHHZVgpzhbJszchsnsLg +tDvflvrGttDCjlQfmCGvtCftczhbzwJczcJgznNmzJNhwgsp +tQlDCDtrfrtlGrjlQBHFHPVHbBbZqTZdVZBF +MTwvsQJMvvHwVMMJMQNNJRPWWjCllrlWGFlSFCpjgFVSWr +zhcmnRZmqmWjCSFrFqCW +ZbmhZcdZznZfndtwDtMMsRQTTQNRQw +ZhhVqQTvZvVhSmQZcClRCLPCgTGGLbgl +dJWHwndMHswswlGbCmclmLHbbP +dnwwNJnjBjwwdddnjndfWvmvSNZQNrVVmZvZFvvQQv +trlrlrZzsjRjdFhlpwdpnpdp +QqLvvLQmLfQTLbLTfHmqHHLqQgFBdCJBBgggCJdhgJwCggBF +DPDvqLqffqfhSVjVPSPtsj +gsnVdcBcjMMntGMh +RQZLRZlZDRJDCzCjblJSDjQZWWTWPCThMTFGNPTNttGwCFMh +pDlQbSlzpQsjVpjHVfgs +zgqtCtJltdGttJgVGPPJCtJvQFsFFbTFssNDNDsHLbTQbssP +rRcwBnnpcmBqpbLHDspTbFsb +mwRqrqrmWrZnfWmBmnRZlgClgJCJlGJzClGMtG +jlzHllmPnpHlHZBWZJJDWMBNVH +bQrhDbcLgsQrtdVCJWfCCBMMVWrJ +QhGdGcLGwwwtcDzznppPpPwlpnSS +qbpqvWFHbFHHsWwPqPpsVWZTlDcLDddddDrmrcVZDrmT +MCgSSJMCztdmcLzlrlDl +QCRMRSnNtRSqqRjsjLPPvp +ZnZrTfsWWvhVSRmzqqnn +pLGBLBgLCpgGpbdLbgMClJTmmhShSRShqSBDQSRRmQVV +dpJPldgMMbglFdrNWWjHZNccTjZP +CCZCQzwwdmMGDWMmhCMJgpnrnwsTrFNLgnpNgg +jfStHtcjqDPbPtvqvgLNpppnHsrsFgnFNp +fcqqPPPtPSfRVBBRPRPbvQzzhQWGZQVQQZDQMMzGQM +VVlDNDgppgtNltlrJPbjSzPPzjsMsjBBMWMM +LmGRmfmwCqQqbsQBMqJj +cHRcCFfmfmGLJLGFcJLFwfdlhDgptthhHpVrNVdhlvhl +vSSdnBVpscwZcBZB +mLHzqtGtNfGHHFNHMhJMthsbcJtctZTw +GHqHHGzNDNFCfqllCFqVDdPSDQnddvcpPQjdjg +CMWcwGTrvzDWzrDccDCGzTTTplZgSjggjSpSljSjBpSmgmWB +nssRttdsnhsdbFhtVFhNpgwNpBBgHHBBBBZSjNSl +PnVPVPLFtvPvTwwrQq +tlQlqlJCCJWgFrprPjpGVpQzvp +SDbwShHbBZZbhcBdDBDSTrsVpPrzzzHVzNllzGlVNv +BTbbScwRhwZLnLtfJFLFJgWl +VDfPVHfDVMMfHSPSMTVfqgFthFcFrtcdhrhDQdDmdcdt +bWGGHCplWnJNpJCCnlnNwdcwQhmmdmtwddBNcc +HpGCnZGllzlzJWjnCbbnCnRvfvsSTVVSgVLqSsLsLzPPLV +fQqcfqfSDzDWffDZ +NcCLCtPCPMtNBwdthpLhPwzsHrszsZssTsWrDrDVTNNH +twMPBtCpLBCtwMPpJcMBSjjnngqSjQQJbQjjmgmn +vQwVQQVqcJvVJvCpQBCLpdgSFCdjjWWnMSgnSjgjbj +hszPRDTVDWWWRnjWWj +TtDDZsszlPllhPzmPVGssTPpQLcpvpBpZpcfpvrvQvBQLv +sRmGqqzzzgCtRrttCP +cffSwNDddTdfGWtgNCrtGMPP +GGcTwHwHvjqLLjLvlJ +JSdjLJMBdMSrfwwLpWgzWmvDhggzWvfmgD +VsRtVllstHHNllsQsHQRzchcnDmvmvnRvvvcnZ +tGVGCTTTtTFVbsTTNTHsTTqBqBLrBCjqBwqJwqBzLqzw +MhjTJjlSDrplQvFQ +RHttqbNGGmbbLmLmdqbgnFQwrZswQrwDpFpppdwfvQ +gCNmDHHRCLHnWWSCjhWPShPz +BvzpbBwBmsDrmGVgZFDm +TnNRdtlRlCdFFGTLffrrGf +jltNtRCPSlPNtcpwpGzjMBpvbhps +hflJphNDmmbpfnfplbcvLsHVLsrsZsVvCb +FgTFWqTBfFPfFqQqTwHsHccVVLQCZZZCVH +BSSRTGWBgFggBWgBGStTGpzNztmjjzhhzDfNnMjnph +mDDFjjFmVlTZJttffD +hhRvNNCvdNMRLzhSzpptwslNTfNQntsJQZZTlN +WCdMzdMzhMdvRvLhCRLPvjgHmggmbmbblgWcGmcbcG +cScMdhsDhDDdvGzZptzGcnGtpB +NPWjJqrjJWwrSFWRJlrlNWJLtZznLBBzZznLqnpqnpnznV +NWNQwNPjCSQTQhTd +fVVCVccppZMZMMCBzJTNJHWZTWZzNF +QrmmPhDqPhsPRhrlbgRDbbPDJNJTnJzmzzfNNTNHNJNWmnvF +DgbPLbPsQsrbsqLbgllsQQptfwSjwtVLfwdcpCjVwwSp +ZlsmlrZZJcQmhBhlNrsrJRRbRCRggRbzGCRHgRCDGB +fMFvdfVTTdjWTTTfvSjVjpjzcCbFHGPHPDbPHRCFGGRHHG +cdvfSWjfjpdVqSwSvMdLrlrmhqZhhrrLLJQhNr +sWVVmDJsNWNjcSNJZcNcZWWsHTGHTChhHGtHsFFbbsfHhH +nqPRwQRgpQRPQQgMQgQLQqBhvTRtfdfvfCbFtTFFFTtvff +qgrPMLLPpVlbDrVrWD +VcGjcCHcVHPrGnjQDQgDgQDFtdglRtlQ +bWWhfzJhvZWJzNpmRTtsDLDgRTsNddFT +MhJMhJbMmSZbJZwSCtjqcGrrnGjC +FCvpgDsZNsCbvvvpVwcDrjcrmVMwVwHJ +fhfWdPhhhhRQQqzdLSRHRHJjBTTmcrTMrMrwmczcwwTz +qndhdQWndftfhWStfLQQfWgFNsgFpHCtgCNbGZZlZCll +mqTCNhTNmGTLwLNfLrSrgZHDvfPDPv +cjsMQppsFnFslnRQQGMDHGZHSgzHPDZDSf +stWFjcFFsJlQcQtwtbVwCmCthmBTGb +fmsffcqhmqPsnTCnCcQpzjSSNpBWBTQpVSSD +vHbgLRvvvzdgjVVjWg +WltLWvWlqcChrhlf +CtwjffWrdznRtzCwLsmGLlLMsMmMGb +cZFFbgPgJZDchMMPVsmlPGmG +SpNFJBJccNgDcTJJTdbStbnntrCdSrjWnb +qWzgNFqzqHNTBzFNCZCGPpPlHmdPblls +rfSJRJnhhnJDjrfvRStCmpdGsdlDpZZZPbPCmW +cffRvfnnVRjFTWVTLQMFWN +VcHhVrVCQQWhffzcRZznnZFf +dDSCGSsSblwDdmLqvnFZzNZplfpfRZfBnl +tCCwGmSqbqtwsVPjVJWtJHHhQV +fvvTcWzGcCJrJGJvvHMbZTmRQTbpMdQQsR +SgFhVgllLgjLgwlwljFqVFSFdjmBHmZdRMdZpbjpmpjBsHdM +LNqFnlDgVqllwLFLnVSgLFZtCzzzzvCGGccCCDCfvJrv +FczpzmSjVVpSQrzzcRpRcrwqMtJqwtvtLHvQwtLtnJMw +TvbGGbNfGCBBLHtJBHDZDMqD +shgdNTGgvNsflspcPjzVdmppczrV +JHLPLTsSllgSSPPSPLTRTdjCZGZDGGgCdqZtZCZdZt +mhFpnpFwqdGbdFDt +prpWcvnmhmpccBBJMJJlPWLHMDSDWW +GcMcjDbDMMjqHBHVlHvv +rLCrwNJCnwrZNLWQQwzQpRqQPlBRVVBRvvtHqf +zhnrnzdrCwLJCwzwCMGcbdFTscTmgcFlgc +cnwlFrdMsggblgsrMbncwrsWzjGBTjznBzWNzPzTzfjTzf +vvVVHSpQvvRQDJGGLWGfTLTBLQMN +hCmJqVvMSpqqChCJHDZrFsdhrtgFhttZZhts +sfDNqLNpqpzCzLsDqzbCVWRhjTNhShTjHmmjjhStBmvT +wZrlwJwFJGlFMTjhBBZTSTRSbv +wrQrgnPwMsnLbfffVc +hDcwwGWhMMssTcdM +NQmLbNSZHQSHSNpbvfdqfRsZMqssjqdd +LNVtLSSHLSgLNrgwJgJGnBwFMBzD +CRDfCbfjcnRCBVfjVMfMjZpPptplPWtppStpSlBqlq +HdTFLGsdLrzNWtvqPTcpgPZl +JLGmmHrwJGwhjmfMcbDjQC +VShGpPbWjcPCcTLcPN +HqfqDfDFFJDvZRJvqZRRqHZdNcwjllwvQQLQlllccwclCMCT +FddsFmJjjrgGmbSSpS +NRFFLtFtqFLGsdnGbQSs +ljMfMBDlJHgBVHgVflfnwdsSQQbddsSsqnqGfs +PlzDzjljzqRzWzZW +dtzZZbctPzwdlzRwlcdfRgtQJmFmhPSmmSsQQFhsmqSFvm +nDjHnNjjjMnfjNTMWhHQWJSqSSQmhqhm +CDpVCfrjLnnfwtBcpdcbcBZt +sssZSZtDfHbbdtBTCRBzRDFJCBLp +jwWgmWlNQNLlcjWhgQlrQQWrCCJJzFCMVMTzpBMMCVCMTwpT +ggLgrqljLlGvHqttftbP +cSGBFsFcSRZSQGsgBNgVMwMhDQDVfqPjMhwwVq +vnCTLlrpPlHzzjbMfqpbww +rJCnlmClvWvLrTmtTlZcZWSSWPGGdNcFGgcR +lfDDvZZSvLtDtCQZltCqVBWVBCbHJjRdNqWq +pGGhhzMRcqMBqMdVBN +mzgwGrrwhThFGPmGPcFGpwStTfltfDftStDsQRsflDQl +LjnSjLZLBcbBdDqzND +rrfhfMRmpsghfrhGhgQrcPNtZcqNCqdCqPzcNZMM +ZTTgvRpmfffpfgRRhWnVSJJLLWnvJHFlFH +lstcGcttdczzsWVCvQVLCHHnQHWL +rjmJrmfmJMqvQTLvqfGG +JbNrjGjGrMDRJghZggcchhDhzc +tftJQwCgSjpdWHjbRJ +DcwvlZBmGvHjdbczcRpb +sqwDlsBvGNSMQTCNfCTC +DwDrtvMHtBCvcpDcjCMFtBCblJfJGJbZlfzrRlJdbRdZld +sPLPmqhSnLQQSWqlbzRRhfJCJfNJhZ +mVCnWCsQqqLTPWmnDVMFVtHFtMBFpjwM +scChGddJztdNswNsdDsthvmpVmRVcZjmvVvRSMZVSZ +lQLCWgWHCWbFPbbbHqLnLPHHVMpVRgSMmZVSBZBjZVSjRBZp +QrTlTHbPnTsJGtsDdGCr +fMjgFqtFWMhtjcNQSDMmNlCCDMQN +sVHdHdJHwPGPGwwbpJGTbGTvClldmvRSnvlDlLLSlvRnQl +pJbHPHJGVbBswpTcfrBtrhmtrFczzq +SDGSDGVPqqqQPGrTQVTQDrSrJfHJgqhgJqzhJJmWfHpWpzmg +twCdCWMLwbtLLjBddgfcJgRHfRRpfcpRHM +FZdbvFFbVvsWsQsW +rzrRgqGrwgjRVqJCHLzCCWhtDbCC +dTZnNpvBvnJdBpBnsJPvsSCbthLtLbbQShQQLHtSST +BlplPmdlFsslfJmmRfwfwMjw +PPHSrmfHTnmHnHBzRhbFgfbFwzQg +LcsVsGtVLtLqpzwBvgzQRgTTTp +TjLJGTTJWJZZWWZS +tHcshJcJRhLsQscVtccJLRHfvlPjZFSvmvSbvfLFfFFbGZ +drwdTNlwwBTpCdCdwGPrrmjjmjmbSjFPrF +wglnzCDpJtQcztMR +bbMjTbBvgjZNSqldTlVt +wwrcFwsrsnnCQzrCsLnRsQZcNlpJVZHdttZVttSZqJZd +GwLnrsmFCCzqzhvPbPmWmvvfjj +dcnwQdcdrJdSwSFBBqfBfwMqfBfzsh +RgmZpWlCClRlTgBZbhHJJsZjfBHZ +DlNVWgWpgDCCNRDJFcrtQGrrVnrcFPtc +sWSHsdSrHWHsbdsddBsbjmfwffmJDJwcfDQgfvwJDj +ZNGPhRqCCRNGNwSDvmmwwgDhgf +lGlTLTGTSVVFqVTqsFHWntbWBsBsnBHb +QRRgRvDwWDVjmSbDnbTDlDnbqS +rHCPPHrcLFJcllqbTlpq +CldFrNFsgVhhhWgN +qSfMgNqfpmSmlQrRFG +cbBczbtbZTcPWzcrTrmRrLGFTQQFmJ +PBZChtzzcWPcZtBvPjtzBBCfHMMNdDgDpMfVfVpHMqNR +LJPPCHtgtLDfFfvTLwfv +pVGWGGjjjplhpGGVjWnldsvrrMFvfDMTWBdFrfFF +cjlhShjchhjGGmNVjplcQgmTPtHPPJmQgQHgtqgZ diff --git a/days/3/sample.txt b/days/3/sample.txt new file mode 100644 index 0000000..f17e726 --- /dev/null +++ b/days/3/sample.txt @@ -0,0 +1,6 @@ +vJrwpWtwJgWrhcsFMMfFFhFp +jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL +PmmdzqPrVvPwwTWBwg +wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn +ttgJtRGJQctTZtZT +CrZsJsPPZsGzwwsLwLmpwMDw From 4a120d3f4533ae83b0aad03d6e222a175c2fbd69 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 4 Dec 2022 12:25:20 +0100 Subject: [PATCH 014/120] Day 3, Task 2: Badges This also contains a refactoring to []byte for the rucksacks, because this more explicitly shows that we know the type of the input -- and the items aren't some "runes", they are really just ASCII bytes and we can safely index into the rucksack string. --- days/3/day3.go | 64 ++++++++++++++++++++++++++++++++++++++++---------- go.mod | 1 + go.sum | 2 ++ 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/days/3/day3.go b/days/3/day3.go index 1d6c372..92a840c 100644 --- a/days/3/day3.go +++ b/days/3/day3.go @@ -4,35 +4,67 @@ import ( _ "embed" "fmt" "strings" - "unicode" + + "golang.org/x/exp/slices" ) -func findCommonItem(compartment1, compartment2 string) (rune, error) { +func findCommonItem(compartment1, compartment2 []byte) (byte, error) { for _, c := range compartment2 { - if strings.ContainsRune(compartment1, c) { + if slices.Contains(compartment1, c) { return c, nil } } - return -1, fmt.Errorf("no common item") + return 0, fmt.Errorf("no common item") +} + +func getPriority(item byte) int { + if item >= 'A' && item <= 'Z' { + return int(item - 'A') + 27 + } else { + return int(item - 'a') + 1 + } } -func calculatePrioritySum(rucksacks []string) (int, error) { - var sum int +func calculateMispackedItemInCompartmentsPrioritySum(rucksacks []string) (int, error) { + sum := 0 for _, rucksack := range rucksacks { - if rucksack == "" { + if len(rucksack) == 0 { continue } + l := len(rucksack) compartment1, compartment2 := rucksack[0:l/2], rucksack[l/2:] - commonItem, err := findCommonItem(compartment1, compartment2) + commonItem, err := findCommonItem([]byte(compartment1), []byte(compartment2)) if err != nil { return 0, fmt.Errorf("cannot find common item for %q: %w", rucksack, err) } - if unicode.IsUpper(commonItem) { - sum += int(commonItem - 'A') + 27 - } else { - sum += int(commonItem - 'a') + 1 + sum += getPriority(commonItem) + } + return sum, nil +} + +func commonItemTypes(list1, list2 []byte) []byte { + result := []byte{} + for _, c := range list2 { + if slices.Contains(result, c) { + continue + } + if slices.Contains(list1, c) { + result = append(result, c) + } + } + return result +} + +func calculateGroupBadgeItemPrioritySum(rucksacks []string) (int, error) { + sum := 0 + for i := 0; i + 3 < len(rucksacks); i += 3 { + common1 := commonItemTypes([]byte(rucksacks[i]), []byte(rucksacks[i+1])) + common := commonItemTypes(common1, []byte(rucksacks[i+2])) + if len(common) != 1 { + return 0, fmt.Errorf("expected only one common item, but got %q", common) } + sum += getPriority(common[0]) } return sum, nil } @@ -54,9 +86,15 @@ func pickInput(useSampleInput bool) string { func Run(useSampleInput bool) { input := pickInput(useSampleInput) rucksacks := strings.Split(input, "\n") - prioritySum, err := calculatePrioritySum(rucksacks) + prioritySum, err := calculateMispackedItemInCompartmentsPrioritySum(rucksacks) if err != nil { panic(err) } fmt.Printf("Sum of priorities: %d\n", prioritySum) + + groupBadgePrioritySym, err := calculateGroupBadgeItemPrioritySum(rucksacks) + if err != nil { + panic(err) + } + fmt.Printf("Group badge priority sum: %d\n", groupBadgePrioritySym) } diff --git a/go.mod b/go.mod index cf2cfca..ba8fe9d 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,5 @@ require github.com/spf13/cobra v1.6.1 require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 ) diff --git a/go.sum b/go.sum index f7673bd..370408c 100644 --- a/go.sum +++ b/go.sum @@ -7,5 +7,7 @@ github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 h1:yZNXmy+j/JpX19vZkVktWqAo7Gny4PBWYYK3zskGpx4= +golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 3240acaa3616a3ef6e82609322e253c3a72c8ef9 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 4 Dec 2022 12:35:27 +0100 Subject: [PATCH 015/120] Extract the `PickInput` helper into a utility package Still a lot of ugliness here, but this already helps. --- days/1/day1.go | 11 +++-------- days/2/day2.go | 13 ++++--------- days/3/day3.go | 12 +++--------- days/util.go | 9 +++++++++ 4 files changed, 19 insertions(+), 26 deletions(-) create mode 100644 days/util.go diff --git a/days/1/day1.go b/days/1/day1.go index e5f3583..33295aa 100644 --- a/days/1/day1.go +++ b/days/1/day1.go @@ -6,6 +6,8 @@ import ( "sort" "strconv" "strings" + + "github.com/ankon/adventofcode/2022/days" ) //go:embed sample.txt @@ -79,16 +81,9 @@ func findHighestCaloriesOnElf(input string, n int) (int, error) { return result, nil } -func pickInput(useSampleInput bool) string { - if useSampleInput { - return sampleInput - } else { - return fullInput - } -} func Run(useSampleInput bool) { - input := pickInput(useSampleInput) + input := days.PickInput(useSampleInput, sampleInput, fullInput) highest, err := findHighestCaloriesOnElf(input, 1) if err != nil { diff --git a/days/2/day2.go b/days/2/day2.go index 985e7d6..92780da 100644 --- a/days/2/day2.go +++ b/days/2/day2.go @@ -4,6 +4,8 @@ import ( _ "embed" "fmt" "strings" + + "github.com/ankon/adventofcode/2022/days" ) //go:embed sample.txt @@ -12,14 +14,6 @@ var sampleInput string //go:embed input.txt var fullInput string -func pickInput(useSampleInput bool) string { - if useSampleInput { - return sampleInput - } else { - return fullInput - } -} - type shape int const ( @@ -73,7 +67,8 @@ func simulateGame(rounds []string, roundValue map[string]int) (int, error) { } func Run(useSampleInput bool) { - input := pickInput(useSampleInput) + input := days.PickInput(useSampleInput, sampleInput, fullInput) + rounds := strings.Split(input, "\n") assumedScore, err := simulateGame(rounds, roundValueSimpleTheory) diff --git a/days/3/day3.go b/days/3/day3.go index 92a840c..b687e37 100644 --- a/days/3/day3.go +++ b/days/3/day3.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + "github.com/ankon/adventofcode/2022/days" "golang.org/x/exp/slices" ) @@ -75,16 +76,9 @@ var sampleInput string //go:embed input.txt var fullInput string -func pickInput(useSampleInput bool) string { - if useSampleInput { - return sampleInput - } else { - return fullInput - } -} - func Run(useSampleInput bool) { - input := pickInput(useSampleInput) + input := days.PickInput(useSampleInput, sampleInput, fullInput) + rucksacks := strings.Split(input, "\n") prioritySum, err := calculateMispackedItemInCompartmentsPrioritySum(rucksacks) if err != nil { diff --git a/days/util.go b/days/util.go new file mode 100644 index 0000000..69b18b3 --- /dev/null +++ b/days/util.go @@ -0,0 +1,9 @@ +package days + +func PickInput(useSampleInput bool, sampleInput string, fullInput string) string { + if useSampleInput { + return sampleInput + } else { + return fullInput + } +} From c55da11bd3252f1c0182377da72ae44e7be60408 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 4 Dec 2022 12:36:26 +0100 Subject: [PATCH 016/120] Fix typo --- cmd/days.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/days.go b/cmd/days.go index c741c6a..d5eba06 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -18,7 +18,7 @@ var day1Cmd = &cobra.Command{ var day2Cmd = &cobra.Command{ Use: "day2", - Short: "Rock Paper Scissor", + Short: "Rock Paper Scissors", Run: func(cmd *cobra.Command, args []string) { day2.Run(useSampleInput) }, From d1dc946e69c9897139028bbbec30b22847173e94 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 4 Dec 2022 12:42:31 +0100 Subject: [PATCH 017/120] Reduce boilerplate in days.go --- cmd/days.go | 42 ++++++++++++++++++++---------------------- days/1/day1.go | 8 +++++--- days/2/day2.go | 8 +++++--- days/3/day3.go | 8 +++++--- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/cmd/days.go b/cmd/days.go index d5eba06..679a42c 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -1,6 +1,8 @@ package cmd import ( + "fmt" + day1 "github.com/ankon/adventofcode/2022/days/1" day2 "github.com/ankon/adventofcode/2022/days/2" day3 "github.com/ankon/adventofcode/2022/days/3" @@ -8,32 +10,28 @@ import ( "github.com/spf13/cobra" ) -var day1Cmd = &cobra.Command{ - Use: "day1", - Short: "Calorie Counting", - Run: func(cmd *cobra.Command, args []string) { - day1.Run(useSampleInput) - }, +type dayRunFunc func(bool) error +type day struct { + short string + run dayRunFunc } -var day2Cmd = &cobra.Command{ - Use: "day2", - Short: "Rock Paper Scissors", - Run: func(cmd *cobra.Command, args []string) { - day2.Run(useSampleInput) - }, -} +var days = []day{ + {"Calorie Counting", day1.Run}, + {"Rock Paper Scissors", day2.Run}, + {"Rucksack Reorganization", day3.Run}, -var day3Cmd = &cobra.Command{ - Use: "day3", - Short: "Rucksack Reorganization", - Run: func(cmd *cobra.Command, args []string) { - day3.Run(useSampleInput) - }, } func init() { - rootCmd.AddCommand(day1Cmd) - rootCmd.AddCommand(day2Cmd) - rootCmd.AddCommand(day3Cmd) + for index, day := range days { + cmd := &cobra.Command{ + Use: fmt.Sprintf("day%d", index + 1), + Short: day.short, + Run: func(cmd *cobra.Command, args []string) { + day.run(useSampleInput) + }, + } + rootCmd.AddCommand(cmd) + } } diff --git a/days/1/day1.go b/days/1/day1.go index 33295aa..58f6ea3 100644 --- a/days/1/day1.go +++ b/days/1/day1.go @@ -82,18 +82,20 @@ func findHighestCaloriesOnElf(input string, n int) (int, error) { } -func Run(useSampleInput bool) { +func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) highest, err := findHighestCaloriesOnElf(input, 1) if err != nil { - panic(err) + return err } fmt.Printf("Highest calorie count on an elf: %d\n", highest) highest3, err := findHighestCaloriesOnElf(input, 3) if err != nil { - panic(err) + return err } fmt.Printf("Sum of the 3 highest calorie counts on an elf: %d\n", highest3) + + return nil } diff --git a/days/2/day2.go b/days/2/day2.go index 92780da..5cde952 100644 --- a/days/2/day2.go +++ b/days/2/day2.go @@ -66,20 +66,22 @@ func simulateGame(rounds []string, roundValue map[string]int) (int, error) { return score, nil } -func Run(useSampleInput bool) { +func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) rounds := strings.Split(input, "\n") assumedScore, err := simulateGame(rounds, roundValueSimpleTheory) if err != nil { - panic(err) + return err } fmt.Printf("Score according to theory about guide: %d\n", assumedScore) actualScore, err := simulateGame(rounds, roundValueActualMeaning) if err != nil { - panic(err) + return err } fmt.Printf("Score according to actual meaning of guide: %d\n", actualScore) + + return nil } diff --git a/days/3/day3.go b/days/3/day3.go index b687e37..9cf48ce 100644 --- a/days/3/day3.go +++ b/days/3/day3.go @@ -76,19 +76,21 @@ var sampleInput string //go:embed input.txt var fullInput string -func Run(useSampleInput bool) { +func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) rucksacks := strings.Split(input, "\n") prioritySum, err := calculateMispackedItemInCompartmentsPrioritySum(rucksacks) if err != nil { - panic(err) + return err } fmt.Printf("Sum of priorities: %d\n", prioritySum) groupBadgePrioritySym, err := calculateGroupBadgeItemPrioritySum(rucksacks) if err != nil { - panic(err) + return err } fmt.Printf("Group badge priority sum: %d\n", groupBadgePrioritySym) + + return nil } From 20aeb31bedb88f39df45b7d319958ae9904f5cdc Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 4 Dec 2022 13:05:30 +0100 Subject: [PATCH 018/120] Day 4, Task 1: Redundancies --- .vscode/launch.json | 4 +- cmd/days.go | 3 +- days/4/day4.go | 72 ++++ days/4/input.txt | 1000 +++++++++++++++++++++++++++++++++++++++++++ days/4/sample.txt | 6 + 5 files changed, 1082 insertions(+), 3 deletions(-) create mode 100644 days/4/day4.go create mode 100644 days/4/input.txt create mode 100644 days/4/sample.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index 45761d3..2336687 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "mode": "debug", "request": "launch", "args": [ - "day3", + "day4", "--sample=true" ], "program": "${workspaceFolder}" @@ -21,7 +21,7 @@ "mode": "debug", "request": "launch", "args": [ - "day3", + "day4", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index 679a42c..6cebed9 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -6,6 +6,7 @@ import ( day1 "github.com/ankon/adventofcode/2022/days/1" day2 "github.com/ankon/adventofcode/2022/days/2" day3 "github.com/ankon/adventofcode/2022/days/3" + day4 "github.com/ankon/adventofcode/2022/days/4" "github.com/spf13/cobra" ) @@ -20,7 +21,7 @@ var days = []day{ {"Calorie Counting", day1.Run}, {"Rock Paper Scissors", day2.Run}, {"Rucksack Reorganization", day3.Run}, - + {"Camp Cleanup", day4.Run}, } func init() { diff --git a/days/4/day4.go b/days/4/day4.go new file mode 100644 index 0000000..65b623f --- /dev/null +++ b/days/4/day4.go @@ -0,0 +1,72 @@ +package _4 + +import ( + _ "embed" + "fmt" + "strconv" + "strings" + + "github.com/ankon/adventofcode/2022/days" +) + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +func scanRange(s string) ([]int, error) { + minS, maxS, found := strings.Cut(s, "-") + if !found { + return []int{}, fmt.Errorf("invalid range %q", s) + } + + min, err := strconv.ParseInt(minS, 10, 0) + if err != nil { + return []int{}, err + } + max, err := strconv.ParseInt(maxS, 10, 0) + if err != nil { + return []int{}, err + } + return []int{int(min), int(max)}, nil +} + +func rangeFullyContains(r1, r2 []int) bool { + if r1[0] <= r2[0] && r1[1] >= r2[1] { + return true + } + if r1[0] >= r2[0] && r1[1] <= r2[1] { + return true + } + return false +} + +func Run(useSampleInput bool) error { + input := days.PickInput(useSampleInput, sampleInput, fullInput) + + count := 0 + for _, pair := range strings.Split(input, "\n") { + if pair == "" { + continue + } + r1, r2, found := strings.Cut(pair, ",") + if !found { + return fmt.Errorf("invalid pair definition %q", pair) + } + range1, err := scanRange(r1) + if err != nil { + return fmt.Errorf("cannot parse range %q: %w", r1, err) + } + range2, err := scanRange(r2) + if err != nil { + return fmt.Errorf("cannot parse range %q: %w", r2, err) + } + if rangeFullyContains(range1, range2) { + count++ + } + } + fmt.Printf("Pairs with fully overlapping ranges: %d\n", count) + + return nil +} diff --git a/days/4/input.txt b/days/4/input.txt new file mode 100644 index 0000000..c7fb3fc --- /dev/null +++ b/days/4/input.txt @@ -0,0 +1,1000 @@ +48-50,48-49 +5-89,5-5 +17-57,55-96 +24-67,23-25 +89-99,11-89 +34-71,35-71 +13-17,16-95 +13-93,5-12 +11-91,1-11 +4-81,2-11 +53-82,52-53 +5-98,4-97 +4-78,3-3 +20-81,21-80 +79-83,77-82 +76-87,43-87 +14-93,12-62 +13-94,15-95 +22-75,14-53 +67-90,67-79 +1-82,1-82 +5-80,83-96 +28-57,56-56 +53-91,52-54 +21-97,2-36 +8-18,10-98 +7-91,12-91 +11-88,19-95 +22-88,21-88 +31-69,9-48 +2-3,3-43 +5-95,2-6 +5-85,5-79 +51-91,51-69 +41-91,41-64 +23-37,24-95 +1-28,3-94 +6-93,6-98 +8-65,34-66 +2-8,9-38 +3-75,2-4 +40-77,37-76 +51-51,11-51 +95-95,3-94 +90-90,81-90 +26-61,26-61 +1-96,97-98 +41-84,90-91 +94-94,1-94 +52-89,74-90 +9-11,10-74 +57-67,56-62 +29-98,30-78 +20-88,18-54 +11-81,10-82 +85-87,26-86 +8-45,46-78 +16-33,20-49 +73-93,16-93 +35-36,29-36 +4-98,98-98 +24-30,30-80 +64-99,72-97 +8-33,8-47 +88-96,93-99 +23-46,35-49 +41-60,40-41 +5-83,4-6 +76-76,15-76 +37-70,69-71 +11-77,11-12 +57-65,65-97 +20-46,46-62 +76-84,8-77 +10-29,29-53 +16-50,6-17 +20-99,19-19 +11-12,12-72 +24-91,77-92 +37-73,72-73 +50-52,73-89 +37-99,25-76 +1-88,1-2 +18-64,17-63 +19-52,17-52 +5-86,6-87 +13-87,14-87 +23-82,19-92 +56-79,57-79 +25-68,26-67 +5-95,94-96 +38-50,38-39 +32-75,32-75 +23-69,23-69 +25-54,18-25 +33-79,34-67 +38-62,38-65 +62-75,69-78 +2-17,3-17 +12-20,19-96 +7-7,4-8 +1-92,2-93 +29-70,69-77 +7-54,2-54 +9-34,16-34 +4-20,7-31 +4-89,4-47 +12-91,9-96 +8-79,9-80 +32-91,31-91 +1-4,5-55 +85-94,84-95 +73-74,6-74 +51-70,52-70 +21-75,7-27 +13-38,37-39 +42-97,42-98 +33-45,28-45 +12-14,13-98 +91-92,90-91 +66-83,57-83 +8-79,9-67 +59-72,71-72 +33-71,3-33 +13-38,12-38 +18-93,18-52 +28-80,12-26 +87-88,2-88 +7-89,7-85 +26-27,27-27 +12-97,12-97 +36-95,32-91 +25-33,25-32 +4-39,5-75 +40-58,41-58 +8-60,8-93 +9-69,70-70 +19-34,35-68 +47-47,38-47 +1-70,1-70 +39-82,38-83 +17-98,17-99 +56-86,37-56 +2-2,4-96 +5-97,97-97 +52-93,52-77 +39-66,38-66 +9-99,4-99 +25-37,24-37 +2-99,1-98 +13-15,15-15 +10-51,5-9 +38-99,19-96 +6-38,37-78 +94-98,95-99 +8-89,29-89 +2-98,1-98 +13-99,99-99 +1-76,1-25 +8-97,8-97 +9-90,89-93 +24-52,7-49 +30-97,45-99 +26-62,26-59 +15-27,21-30 +80-81,64-80 +65-76,2-76 +9-9,10-99 +3-6,4-82 +78-79,20-79 +11-50,49-49 +10-12,11-68 +1-5,4-85 +8-10,9-95 +16-86,16-87 +11-81,10-11 +36-87,75-87 +55-92,54-99 +3-18,18-84 +4-73,1-2 +16-66,5-76 +29-73,29-79 +60-91,67-91 +82-82,47-82 +31-38,31-37 +44-44,21-44 +93-94,65-94 +13-79,2-12 +4-97,5-97 +40-78,40-41 +69-99,1-69 +8-97,8-96 +27-27,26-79 +60-96,71-88 +24-57,18-25 +1-26,2-27 +53-81,69-81 +3-96,2-96 +9-99,9-97 +45-48,46-56 +6-36,5-30 +45-73,46-73 +28-41,27-42 +4-91,90-94 +6-39,20-44 +3-3,5-65 +17-98,18-65 +15-98,15-96 +29-88,65-90 +10-61,60-62 +26-91,27-91 +78-96,95-95 +6-22,6-17 +40-56,40-57 +4-5,6-98 +78-83,51-83 +8-78,8-78 +26-87,26-86 +4-94,3-4 +5-55,2-6 +40-50,19-56 +55-68,2-94 +39-41,9-40 +68-76,68-69 +51-60,50-59 +9-48,2-10 +13-96,13-63 +1-90,4-91 +1-7,6-99 +25-67,25-66 +13-94,14-93 +27-28,28-70 +39-41,25-40 +8-53,9-53 +56-89,57-88 +4-56,50-56 +22-76,15-17 +7-98,69-76 +12-46,11-46 +1-41,3-72 +43-55,44-76 +9-81,9-81 +45-95,45-94 +12-68,12-69 +90-96,74-85 +67-68,68-68 +50-73,2-73 +6-17,6-97 +70-76,71-99 +9-43,9-43 +9-76,8-75 +66-90,65-66 +13-99,12-14 +1-2,3-91 +53-86,52-53 +3-57,3-96 +81-92,80-92 +6-18,17-88 +70-94,69-69 +17-17,18-88 +4-92,4-93 +41-61,47-61 +25-52,25-73 +78-97,12-97 +39-54,38-46 +39-52,39-58 +8-99,8-51 +52-58,51-52 +5-45,6-46 +3-99,98-98 +84-87,84-98 +58-87,86-88 +6-72,71-73 +41-42,41-86 +27-42,27-77 +14-15,14-74 +43-43,40-43 +17-95,17-93 +44-66,65-70 +4-99,5-99 +43-43,44-86 +64-75,63-71 +4-99,5-99 +6-29,6-99 +19-84,18-83 +72-72,10-72 +9-14,13-88 +3-98,98-98 +9-81,10-81 +13-69,13-70 +3-87,1-87 +22-61,10-62 +75-90,75-90 +69-99,68-87 +94-94,91-95 +2-3,3-96 +5-93,48-93 +43-45,33-49 +85-87,2-86 +51-52,52-62 +50-91,40-49 +1-81,21-81 +51-56,51-56 +22-23,23-37 +25-27,26-67 +58-59,23-58 +37-85,84-85 +12-97,12-96 +14-38,2-13 +33-81,32-44 +34-65,46-60 +3-28,27-28 +11-54,11-55 +2-93,1-93 +28-28,28-50 +10-82,81-83 +77-82,77-82 +33-63,49-63 +2-84,89-91 +37-90,36-91 +46-85,45-85 +97-97,14-97 +5-18,6-19 +7-94,6-95 +17-87,12-86 +11-85,39-85 +7-94,7-93 +9-98,9-96 +18-18,19-96 +62-62,34-62 +24-36,24-91 +72-91,4-91 +7-84,7-83 +9-93,9-87 +22-99,21-99 +32-46,31-32 +32-70,69-97 +13-89,12-88 +10-10,11-89 +46-46,47-64 +51-51,24-52 +5-51,3-3 +46-90,99-99 +6-96,5-95 +50-96,50-97 +96-96,4-70 +13-36,12-35 +19-90,13-20 +12-43,42-95 +1-83,1-84 +3-5,4-70 +24-97,25-98 +27-40,1-50 +37-82,36-83 +47-95,47-94 +2-80,2-58 +64-83,63-87 +42-52,41-44 +26-97,1-97 +35-45,35-78 +6-45,28-82 +11-17,11-16 +67-67,44-67 +2-95,2-94 +22-95,22-94 +20-43,21-92 +33-60,59-76 +6-75,7-75 +3-90,96-99 +38-76,41-76 +18-98,6-19 +2-65,64-77 +3-88,2-88 +14-94,13-93 +40-89,71-99 +44-93,44-72 +48-62,48-61 +6-27,6-26 +43-53,43-54 +4-97,36-98 +8-13,12-83 +15-96,7-96 +18-91,17-18 +11-13,12-55 +31-92,19-94 +44-87,14-45 +18-51,17-18 +23-24,27-27 +23-46,24-88 +12-90,13-90 +37-70,34-70 +1-98,88-98 +2-93,6-95 +73-99,74-98 +4-46,2-46 +50-52,51-75 +45-91,46-90 +11-85,58-94 +26-43,26-44 +56-95,55-94 +10-93,11-92 +1-99,1-99 +8-95,7-7 +19-69,9-18 +18-90,9-60 +74-93,13-73 +62-90,61-72 +7-53,52-95 +44-82,4-44 +17-88,17-88 +26-27,26-89 +1-9,1-62 +13-40,39-62 +2-93,1-92 +91-91,17-91 +57-58,58-85 +23-98,97-99 +16-48,16-48 +25-61,61-87 +14-47,13-84 +46-96,47-94 +8-98,7-99 +3-5,4-97 +38-83,28-82 +7-99,6-34 +23-91,38-84 +33-35,34-63 +14-55,55-55 +34-50,11-35 +3-69,4-69 +67-99,99-99 +38-94,2-59 +2-98,2-97 +77-79,42-78 +6-45,44-45 +39-79,61-93 +5-92,5-97 +4-61,3-64 +47-48,48-67 +11-23,10-23 +2-99,9-99 +31-99,30-81 +28-87,29-88 +8-31,2-13 +3-17,16-83 +29-58,57-59 +4-75,15-35 +49-94,48-93 +23-85,84-84 +7-92,7-97 +53-91,91-97 +26-95,1-95 +9-22,7-9 +13-63,62-95 +54-55,54-97 +80-88,79-88 +1-44,2-44 +3-83,1-4 +95-95,26-95 +23-26,23-26 +19-35,19-34 +17-34,34-34 +39-89,75-97 +42-84,84-84 +60-95,61-94 +6-88,5-88 +2-68,1-68 +16-76,15-16 +30-93,9-96 +10-91,11-91 +36-88,35-36 +24-67,45-66 +41-58,16-96 +84-85,83-85 +10-59,18-59 +33-70,69-69 +58-69,57-58 +4-6,68-85 +3-91,91-91 +99-99,2-98 +33-94,93-95 +68-69,27-68 +4-4,5-14 +98-98,2-97 +5-91,90-92 +2-91,2-90 +37-81,80-80 +9-51,54-69 +45-59,46-59 +8-69,7-69 +20-21,21-29 +45-83,88-91 +22-87,20-21 +4-77,3-76 +50-81,49-49 +47-59,58-78 +22-85,21-84 +3-86,7-91 +63-83,62-63 +10-58,7-57 +14-88,14-88 +18-67,16-28 +39-50,39-42 +9-85,8-85 +7-28,7-8 +72-72,19-73 +25-27,25-56 +40-43,40-43 +10-26,25-25 +29-99,30-99 +9-14,13-92 +9-17,10-56 +93-94,1-94 +31-67,30-68 +15-84,84-84 +45-46,8-46 +10-93,10-94 +31-48,5-94 +49-93,92-92 +45-80,40-67 +63-94,7-93 +2-94,1-66 +26-44,41-53 +51-94,1-94 +5-93,4-92 +14-86,85-86 +9-52,8-10 +24-61,23-62 +1-78,77-79 +6-97,17-96 +43-65,19-43 +45-99,35-99 +58-58,20-57 +22-89,64-85 +12-22,21-80 +6-36,36-36 +1-92,87-92 +26-99,26-97 +7-85,1-85 +20-98,20-98 +2-51,2-54 +73-95,74-95 +16-54,15-17 +4-95,4-96 +11-98,11-98 +67-79,66-80 +61-61,62-63 +50-62,12-50 +9-80,9-81 +1-1,3-87 +16-61,15-23 +31-35,34-40 +13-89,12-90 +89-91,90-95 +20-60,12-81 +2-65,1-66 +38-96,56-96 +23-23,12-22 +96-96,11-95 +8-37,36-97 +2-26,1-26 +30-71,37-73 +71-87,70-70 +31-99,31-82 +6-39,2-7 +1-99,3-99 +29-73,32-81 +33-37,33-36 +15-41,14-40 +32-33,33-90 +23-85,22-24 +26-93,26-86 +3-97,2-98 +10-92,92-94 +29-55,30-55 +9-75,29-96 +6-94,93-97 +63-63,52-63 +24-78,5-5 +38-67,37-67 +14-32,13-32 +35-94,36-94 +23-92,24-92 +9-36,8-36 +63-95,62-62 +37-78,3-78 +34-51,17-37 +84-85,13-84 +1-95,1-98 +18-56,18-19 +17-78,13-16 +6-52,15-44 +13-33,14-33 +10-88,11-89 +61-80,61-79 +6-98,98-98 +1-91,1-85 +60-86,10-87 +3-96,95-98 +34-99,33-98 +19-21,20-91 +7-96,8-96 +2-90,2-90 +36-96,36-96 +76-96,60-75 +8-44,7-44 +9-28,10-28 +10-95,7-95 +56-68,29-82 +10-97,18-99 +68-97,45-97 +19-92,2-92 +6-97,5-97 +74-74,73-73 +20-70,20-70 +18-66,19-67 +91-94,7-92 +4-47,4-47 +11-93,12-93 +33-54,32-53 +54-64,55-63 +20-99,20-21 +39-82,56-68 +4-36,36-47 +30-41,25-31 +65-69,69-69 +20-71,71-74 +16-36,24-54 +2-96,95-98 +11-70,10-12 +5-36,35-95 +36-92,36-37 +37-78,32-87 +28-89,15-88 +9-63,62-62 +2-94,4-94 +85-85,72-85 +30-73,7-31 +10-36,10-36 +75-97,47-95 +23-23,4-24 +49-88,36-87 +25-25,26-42 +33-86,26-86 +13-76,76-76 +60-60,60-60 +3-23,24-24 +4-85,10-85 +7-38,8-37 +40-85,41-84 +46-86,47-87 +8-38,7-38 +76-78,9-77 +80-94,57-94 +86-96,86-97 +35-89,10-67 +45-94,35-81 +8-93,7-8 +22-48,23-47 +21-94,20-94 +63-72,60-73 +89-89,57-90 +34-41,41-78 +5-5,2-6 +1-79,1-80 +79-82,80-83 +37-37,38-53 +65-93,64-96 +33-85,33-33 +7-98,44-57 +2-5,4-69 +19-69,18-68 +80-81,7-81 +19-99,20-99 +5-34,4-14 +4-88,88-89 +51-91,59-93 +33-60,33-58 +32-67,27-94 +8-98,7-8 +34-43,44-69 +10-80,10-11 +7-73,11-73 +23-69,24-69 +68-83,6-68 +2-35,5-35 +1-4,3-90 +88-89,30-89 +57-99,14-63 +16-29,17-28 +67-82,62-77 +20-65,19-66 +37-69,61-63 +58-94,94-94 +1-72,72-72 +7-11,10-47 +18-59,59-59 +57-57,37-58 +60-81,54-72 +2-86,1-87 +7-78,7-77 +59-69,59-65 +15-16,15-73 +15-82,16-92 +8-88,57-88 +36-92,36-88 +59-60,24-59 +4-22,1-3 +44-60,45-60 +90-95,35-89 +21-30,20-30 +4-83,83-83 +16-99,7-17 +11-18,19-95 +45-94,44-94 +3-11,3-12 +9-70,8-10 +1-8,8-78 +1-5,4-97 +30-55,29-31 +7-89,8-89 +47-47,46-48 +66-96,38-84 +33-34,33-73 +2-23,1-22 +52-64,53-91 +9-34,19-61 +25-57,25-57 +1-98,97-98 +79-89,76-80 +28-80,28-80 +13-77,76-78 +3-88,2-88 +69-72,70-72 +91-91,22-91 +77-95,76-94 +84-92,84-91 +55-99,56-99 +1-91,2-91 +33-36,27-36 +79-84,62-74 +52-54,18-53 +26-37,25-27 +55-85,40-85 +58-74,10-59 +6-53,6-53 +42-49,42-47 +47-79,80-97 +11-24,25-91 +83-87,86-87 +1-88,1-96 +55-63,54-62 +76-76,8-76 +3-78,78-99 +1-86,8-96 +44-70,43-70 +25-27,26-91 +65-98,97-97 +14-64,15-65 +9-36,8-35 +78-84,77-85 +42-58,41-59 +60-92,59-60 +95-97,14-86 +8-82,7-83 +5-58,5-59 +5-99,6-99 +4-13,1-4 +57-86,43-58 +11-82,11-11 +4-87,1-5 +6-7,7-11 +6-22,2-7 +15-49,14-49 +39-97,99-99 +12-49,13-90 +70-80,71-80 +46-95,66-94 +94-98,13-94 +3-11,11-11 +13-23,12-23 +11-98,11-98 +20-99,8-20 +28-87,27-87 +16-21,21-61 +2-91,7-56 +7-7,8-71 +74-74,67-74 +23-88,1-74 +1-99,2-98 +34-85,40-86 +6-85,6-68 +28-31,31-49 +13-40,13-40 +55-56,56-56 +70-72,26-71 +93-94,34-93 +45-75,44-75 +4-10,10-50 +65-74,65-77 +39-87,6-59 +11-85,3-85 +8-46,12-46 +9-9,10-95 +30-41,27-92 +13-97,9-96 +21-62,22-63 +54-69,52-53 +17-99,18-99 +75-92,7-76 +38-39,38-90 +50-69,49-50 +65-87,65-99 +6-98,6-96 +34-62,40-90 +33-47,34-48 +33-95,34-95 +42-99,43-98 +70-85,1-71 +37-63,38-63 +12-17,17-72 +28-31,29-92 +18-69,8-17 +41-96,40-95 +7-86,7-86 +68-78,67-73 +4-6,7-99 +8-86,86-87 +5-6,6-37 +88-94,89-95 +33-74,33-74 +86-87,86-87 +29-55,62-78 +23-38,13-38 +9-44,10-89 +18-67,19-97 +3-83,1-66 +55-81,55-81 +6-72,7-71 +5-55,6-55 +14-99,14-97 +39-83,16-40 +11-73,55-73 +4-68,5-67 +66-73,26-73 +3-92,3-91 +36-59,33-35 +72-73,4-73 +1-83,2-83 +25-88,25-43 +45-71,45-73 +9-96,95-95 +4-5,7-23 +48-50,4-49 +45-96,44-96 +50-87,49-50 +98-99,27-96 +4-40,40-78 +3-94,94-94 +7-34,25-26 +72-79,23-72 +2-84,3-83 +78-96,25-78 +77-94,73-94 +63-66,62-65 +25-80,24-80 +10-33,78-90 +25-55,24-54 +58-62,23-64 +61-62,62-84 +83-83,46-84 +23-30,31-92 +8-95,94-99 +35-65,34-64 +12-19,12-18 +21-25,24-43 +54-79,54-84 +37-56,37-57 +77-77,15-77 +57-88,55-88 +7-93,8-93 +5-89,3-66 +33-63,32-33 +9-52,51-96 +7-97,6-66 +3-58,1-3 +26-85,25-84 +11-63,10-12 +52-54,53-54 +23-68,22-22 +14-96,14-95 +4-41,3-21 +4-6,5-83 +97-98,1-97 +13-90,73-88 +11-15,7-10 +65-80,24-81 +48-82,48-83 +81-87,4-81 +40-47,40-47 +15-87,14-75 +30-50,29-30 +26-65,64-64 +37-37,7-37 +51-51,49-51 +5-71,7-70 +18-54,53-54 +47-48,48-60 +26-98,25-97 +5-6,5-81 +3-98,3-99 +9-22,21-22 +4-97,1-1 +36-36,37-77 +22-35,4-23 +18-95,19-96 +14-94,14-96 +43-46,47-50 +80-91,81-91 +20-67,5-81 +8-87,9-86 +30-69,23-30 +96-99,2-96 +59-75,74-76 +20-66,19-66 +10-85,10-65 +9-82,8-38 +32-66,54-66 +23-64,63-65 +1-89,1-90 +1-95,1-94 +12-82,7-64 +55-66,60-66 +3-93,3-42 +45-87,15-88 +3-50,3-76 +7-86,8-79 +39-39,40-85 +57-86,52-52 +17-84,16-18 +63-99,64-99 +83-94,83-94 +12-85,11-86 +18-89,17-17 +12-25,13-87 +9-12,10-15 +62-92,85-88 +26-97,26-94 +16-94,94-94 +47-83,47-83 +25-86,85-88 +1-99,1-98 +47-87,87-99 +9-99,9-97 +8-73,2-73 +45-47,46-85 +18-95,18-96 +41-41,40-41 +1-4,4-61 +4-95,5-96 +8-79,78-80 +6-81,9-81 +7-90,1-7 +6-22,6-22 +32-82,15-59 +19-93,13-93 +43-48,12-99 +45-45,46-59 +27-69,1-28 +78-78,59-79 +12-57,57-57 +4-39,4-77 +55-91,91-91 +27-87,92-95 +83-87,87-98 +22-84,22-31 +3-91,3-22 +45-86,57-62 +68-82,55-82 +96-98,3-97 +12-32,1-32 +37-71,37-71 +31-59,31-59 +86-88,79-88 +4-92,3-3 +40-91,17-91 +51-52,52-74 +2-97,1-98 +50-83,82-83 +34-34,35-41 +6-47,5-5 +5-65,5-47 +32-77,33-85 +21-68,22-67 +12-45,46-95 +45-48,38-46 +39-84,35-40 +4-60,3-4 +67-83,68-84 +24-92,25-93 diff --git a/days/4/sample.txt b/days/4/sample.txt new file mode 100644 index 0000000..9f9e9cf --- /dev/null +++ b/days/4/sample.txt @@ -0,0 +1,6 @@ +2-4,6-8 +2-3,4-5 +5-7,7-9 +2-8,3-7 +6-6,4-6 +2-6,4-8 From 0a38a2d62b765a8f0cb623dd637143b922c9f0c4 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 4 Dec 2022 13:10:36 +0100 Subject: [PATCH 019/120] Day 4, Task 2: Overlapping --- days/4/day4.go | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/days/4/day4.go b/days/4/day4.go index 65b623f..55cb922 100644 --- a/days/4/day4.go +++ b/days/4/day4.go @@ -42,10 +42,27 @@ func rangeFullyContains(r1, r2 []int) bool { return false } +func rangeOverlaps(r1, r2 []int) bool { + if r1[0] <= r2[0] && r1[1] >= r2[0] { + return true + } + if r1[0] <= r2[1] && r1[1] >= r2[1] { + return true + } + if r2[0] <= r1[0] && r2[1] >= r1[1] { + return true + } + if r2[0] <= r1[1] && r2[1] >= r1[1] { + return true + } + return false +} + func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) - count := 0 + containedCount := 0 + overlapCount := 0 for _, pair := range strings.Split(input, "\n") { if pair == "" { continue @@ -63,10 +80,14 @@ func Run(useSampleInput bool) error { return fmt.Errorf("cannot parse range %q: %w", r2, err) } if rangeFullyContains(range1, range2) { - count++ + containedCount++ + } + if rangeOverlaps(range1, range2) { + overlapCount++ } } - fmt.Printf("Pairs with fully overlapping ranges: %d\n", count) + fmt.Printf("Pairs with fully contained ranges: %d\n", containedCount) + fmt.Printf("Pairs with overlapping ranges: %d\n", overlapCount) return nil } From 6cb2325c399058ee06fa2035dd1e27ab9ef077c1 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 5 Dec 2022 19:12:41 +0100 Subject: [PATCH 020/120] Day 5, Task 1: Hanoi. Not. --- .vscode/launch.json | 4 +- cmd/days.go | 2 + days/5/day5.go | 147 +++++++++++++ days/5/input.txt | 514 ++++++++++++++++++++++++++++++++++++++++++++ days/5/sample.txt | 9 + 5 files changed, 674 insertions(+), 2 deletions(-) create mode 100644 days/5/day5.go create mode 100644 days/5/input.txt create mode 100644 days/5/sample.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index 2336687..e8c7be6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "mode": "debug", "request": "launch", "args": [ - "day4", + "day5", "--sample=true" ], "program": "${workspaceFolder}" @@ -21,7 +21,7 @@ "mode": "debug", "request": "launch", "args": [ - "day4", + "day5", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index 6cebed9..8aa7f3d 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -7,6 +7,7 @@ import ( day2 "github.com/ankon/adventofcode/2022/days/2" day3 "github.com/ankon/adventofcode/2022/days/3" day4 "github.com/ankon/adventofcode/2022/days/4" + day5 "github.com/ankon/adventofcode/2022/days/5" "github.com/spf13/cobra" ) @@ -22,6 +23,7 @@ var days = []day{ {"Rock Paper Scissors", day2.Run}, {"Rucksack Reorganization", day3.Run}, {"Camp Cleanup", day4.Run}, + {"Supply Stacks", day5.Run}, } func init() { diff --git a/days/5/day5.go b/days/5/day5.go new file mode 100644 index 0000000..4d852e3 --- /dev/null +++ b/days/5/day5.go @@ -0,0 +1,147 @@ +package _5 + +import ( + _ "embed" + "fmt" + "math" + "strings" + + "github.com/ankon/adventofcode/2022/days" +) + +type stack struct { + // Crates are named by single (upper-case) letters. + crates []byte +} + +func (s *stack) Top() byte { + return s.crates[len(s.crates)-1] +} + +func (s *stack) Pop() byte { + end := len(s.crates)-1 + result := s.crates[end] + s.crates = s.crates[:end] + return result +} + +func (s *stack) Push(x byte) { + s.crates = append(s.crates, x) +} + +type action struct { + from int + to int + count int +} + +type parseState int +const ( + parsing_stacks parseState = 1 + parsing_actions parseState = 2 +) + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +func simulateActions(stacks []stack, actions []action) error { + for _, action := range actions { + for i := 0; i < action.count; i++ { + x := stacks[action.from - 1].Pop() + stacks[action.to - 1].Push(x) + } + } + return nil +} + +func parseAction(l string) (action, error) { + var count, from, to int + + n, err := fmt.Sscanf(l, "move %d from %d to %d", &count, &from, &to) + if err != nil { + return action{}, err + } + if n != 3 { + return action{}, fmt.Errorf("unexpected number of fields %d, expected 3", n) + } + return action{from,to,count}, nil +} + +func parseStacks(stackLines []string) ([]stack, error) { + stackNames := stackLines[len(stackLines) - 1] + stacks := make([]stack, int(math.Ceil(float64(len(stackNames)) / 4))) + for i := len(stackLines) - 2; i >= 0; i-- { + stackLine := stackLines[i] + for s := 0; s < (len(stackLine) + 1) / 4; s++ { + var crate byte + n, err := fmt.Sscanf(stackLine[s*4:], "[%c]", &crate) + if err == nil { + if n != 1 { + return nil, fmt.Errorf("expected 1 result, got %d", n) + } + stacks[s].Push(crate) + } + } + } + + return stacks, nil +} + +func parseInput(input string) (stacks []stack, actions []action, err error) { + s := parsing_stacks + stackLines := []string{} + + // Read lines until empty line + // Line before empty line: Stack ids + // Lines before that: stack contents + // Read actions + for _, line := range strings.Split(input, "\n") { + if s == parsing_stacks { + if line == "" { + stacks, err = parseStacks(stackLines) + if err != nil { + return nil, nil, err + } + s = parsing_actions + } else { + stackLines = append(stackLines, line) + } + } else if s == parsing_actions { + if line == "" { + break + } + + action, err := parseAction(line) + if err != nil { + return nil, nil, err + } + + actions = append(actions, action) + } + } + + return stacks, actions, nil +} + +func Run(useSampleInput bool) error { + input := days.PickInput(useSampleInput, sampleInput, fullInput) + stacks, actions, err := parseInput(input) + if err != nil { + return fmt.Errorf("cannot parse input: %w", err) + } + err = simulateActions(stacks, actions) + if err != nil { + return fmt.Errorf("cannot simulate actions: %w", err) + } + + topCrates := "" + for _, stack := range stacks { + topCrates += string(stack.Top()) + } + fmt.Printf("Top crates: %s\n", topCrates) + + return nil +} diff --git a/days/5/input.txt b/days/5/input.txt new file mode 100644 index 0000000..198d0b7 --- /dev/null +++ b/days/5/input.txt @@ -0,0 +1,514 @@ +[N] [C] [Q] +[W] [J] [L] [J] [V] +[F] [N] [D] [L] [S] [W] +[R] [S] [F] [G] [R] [V] [Z] +[Z] [G] [Q] [C] [W] [C] [F] [G] +[S] [Q] [V] [P] [S] [F] [D] [R] [S] +[M] [P] [R] [Z] [P] [D] [N] [N] [M] +[D] [W] [W] [F] [T] [H] [Z] [W] [R] + 1 2 3 4 5 6 7 8 9 + +move 1 from 3 to 9 +move 3 from 5 to 3 +move 4 from 2 to 5 +move 4 from 1 to 2 +move 3 from 5 to 7 +move 3 from 1 to 2 +move 4 from 8 to 7 +move 4 from 9 to 7 +move 4 from 2 to 7 +move 2 from 3 to 6 +move 3 from 6 to 2 +move 5 from 4 to 7 +move 7 from 3 to 7 +move 5 from 6 to 9 +move 2 from 4 to 8 +move 1 from 3 to 2 +move 4 from 2 to 7 +move 2 from 2 to 8 +move 8 from 8 to 5 +move 1 from 2 to 4 +move 1 from 2 to 9 +move 7 from 5 to 4 +move 31 from 7 to 1 +move 9 from 9 to 3 +move 12 from 1 to 9 +move 15 from 1 to 7 +move 4 from 3 to 8 +move 2 from 5 to 1 +move 12 from 7 to 5 +move 2 from 8 to 2 +move 12 from 5 to 4 +move 1 from 3 to 5 +move 6 from 1 to 3 +move 1 from 1 to 5 +move 1 from 8 to 7 +move 1 from 8 to 5 +move 7 from 7 to 8 +move 5 from 8 to 2 +move 11 from 4 to 2 +move 10 from 3 to 1 +move 1 from 7 to 5 +move 10 from 1 to 3 +move 5 from 4 to 2 +move 1 from 4 to 6 +move 7 from 2 to 3 +move 9 from 9 to 5 +move 15 from 2 to 3 +move 1 from 9 to 1 +move 7 from 5 to 3 +move 1 from 2 to 4 +move 2 from 9 to 2 +move 1 from 8 to 9 +move 5 from 5 to 3 +move 1 from 8 to 7 +move 1 from 2 to 4 +move 1 from 7 to 6 +move 1 from 1 to 6 +move 1 from 6 to 9 +move 1 from 5 to 4 +move 1 from 6 to 4 +move 1 from 6 to 8 +move 2 from 9 to 4 +move 12 from 3 to 1 +move 8 from 4 to 8 +move 1 from 9 to 8 +move 10 from 8 to 6 +move 1 from 6 to 7 +move 6 from 6 to 9 +move 1 from 2 to 7 +move 1 from 4 to 7 +move 2 from 7 to 3 +move 1 from 1 to 3 +move 6 from 9 to 1 +move 2 from 6 to 7 +move 12 from 1 to 3 +move 5 from 1 to 9 +move 1 from 7 to 3 +move 38 from 3 to 7 +move 19 from 7 to 8 +move 19 from 8 to 2 +move 1 from 9 to 6 +move 5 from 3 to 7 +move 2 from 6 to 7 +move 1 from 3 to 9 +move 2 from 3 to 6 +move 4 from 2 to 6 +move 6 from 2 to 4 +move 14 from 7 to 9 +move 8 from 2 to 5 +move 19 from 9 to 3 +move 6 from 4 to 1 +move 6 from 1 to 4 +move 4 from 4 to 3 +move 10 from 7 to 6 +move 1 from 6 to 4 +move 22 from 3 to 1 +move 5 from 1 to 6 +move 5 from 5 to 8 +move 1 from 7 to 4 +move 1 from 2 to 3 +move 15 from 6 to 9 +move 3 from 8 to 4 +move 2 from 3 to 1 +move 6 from 9 to 1 +move 1 from 3 to 9 +move 1 from 3 to 1 +move 1 from 5 to 9 +move 1 from 7 to 1 +move 1 from 8 to 2 +move 6 from 9 to 2 +move 2 from 9 to 1 +move 3 from 6 to 3 +move 2 from 9 to 5 +move 1 from 6 to 7 +move 2 from 2 to 7 +move 3 from 3 to 5 +move 1 from 8 to 9 +move 7 from 4 to 7 +move 1 from 6 to 3 +move 2 from 9 to 5 +move 10 from 1 to 5 +move 19 from 1 to 8 +move 9 from 7 to 1 +move 1 from 3 to 5 +move 2 from 2 to 4 +move 2 from 2 to 6 +move 2 from 6 to 4 +move 7 from 1 to 7 +move 3 from 7 to 3 +move 2 from 4 to 1 +move 3 from 3 to 4 +move 1 from 2 to 4 +move 2 from 4 to 1 +move 2 from 4 to 8 +move 20 from 8 to 2 +move 1 from 8 to 3 +move 4 from 7 to 8 +move 14 from 2 to 6 +move 3 from 1 to 2 +move 2 from 1 to 7 +move 1 from 4 to 6 +move 1 from 1 to 5 +move 4 from 2 to 8 +move 3 from 7 to 6 +move 1 from 4 to 6 +move 2 from 7 to 9 +move 1 from 2 to 6 +move 1 from 3 to 1 +move 3 from 5 to 8 +move 1 from 1 to 4 +move 2 from 9 to 5 +move 4 from 6 to 7 +move 1 from 4 to 1 +move 1 from 8 to 5 +move 1 from 7 to 6 +move 1 from 2 to 9 +move 2 from 7 to 1 +move 1 from 1 to 3 +move 1 from 7 to 2 +move 4 from 2 to 7 +move 1 from 1 to 3 +move 2 from 3 to 2 +move 9 from 8 to 3 +move 1 from 8 to 6 +move 2 from 7 to 3 +move 1 from 7 to 4 +move 1 from 9 to 7 +move 1 from 7 to 2 +move 2 from 2 to 8 +move 6 from 5 to 2 +move 5 from 3 to 7 +move 1 from 4 to 7 +move 3 from 7 to 1 +move 11 from 5 to 8 +move 2 from 1 to 6 +move 2 from 1 to 8 +move 2 from 5 to 9 +move 1 from 7 to 2 +move 2 from 5 to 4 +move 17 from 6 to 7 +move 1 from 4 to 1 +move 1 from 1 to 7 +move 1 from 6 to 5 +move 1 from 6 to 2 +move 9 from 2 to 5 +move 1 from 6 to 7 +move 9 from 7 to 4 +move 3 from 7 to 8 +move 3 from 3 to 4 +move 8 from 7 to 9 +move 11 from 8 to 1 +move 1 from 4 to 3 +move 1 from 7 to 4 +move 9 from 9 to 4 +move 5 from 1 to 7 +move 8 from 5 to 1 +move 3 from 3 to 4 +move 6 from 7 to 9 +move 3 from 8 to 5 +move 1 from 3 to 8 +move 1 from 5 to 8 +move 2 from 9 to 1 +move 3 from 9 to 7 +move 2 from 7 to 9 +move 3 from 9 to 8 +move 1 from 7 to 3 +move 1 from 3 to 9 +move 7 from 4 to 3 +move 18 from 4 to 2 +move 8 from 1 to 6 +move 1 from 6 to 7 +move 2 from 3 to 1 +move 14 from 2 to 6 +move 5 from 1 to 6 +move 5 from 3 to 2 +move 2 from 9 to 5 +move 3 from 1 to 8 +move 1 from 7 to 9 +move 3 from 5 to 1 +move 4 from 8 to 4 +move 1 from 2 to 7 +move 6 from 2 to 5 +move 2 from 1 to 6 +move 14 from 6 to 1 +move 2 from 4 to 7 +move 2 from 4 to 6 +move 12 from 1 to 6 +move 8 from 8 to 3 +move 11 from 6 to 1 +move 1 from 1 to 6 +move 15 from 6 to 9 +move 3 from 7 to 3 +move 11 from 1 to 4 +move 3 from 5 to 3 +move 10 from 9 to 5 +move 2 from 6 to 9 +move 2 from 2 to 5 +move 6 from 3 to 7 +move 7 from 9 to 3 +move 2 from 1 to 8 +move 1 from 9 to 6 +move 12 from 3 to 4 +move 13 from 5 to 6 +move 2 from 7 to 4 +move 3 from 7 to 5 +move 2 from 8 to 4 +move 15 from 6 to 5 +move 22 from 4 to 5 +move 2 from 3 to 6 +move 1 from 7 to 8 +move 2 from 1 to 2 +move 13 from 5 to 3 +move 1 from 8 to 6 +move 1 from 6 to 4 +move 1 from 2 to 7 +move 7 from 5 to 2 +move 4 from 4 to 8 +move 1 from 6 to 3 +move 3 from 5 to 6 +move 2 from 8 to 9 +move 4 from 5 to 1 +move 1 from 9 to 8 +move 4 from 2 to 5 +move 1 from 7 to 6 +move 4 from 6 to 3 +move 1 from 6 to 9 +move 1 from 9 to 6 +move 4 from 1 to 6 +move 1 from 9 to 4 +move 4 from 6 to 3 +move 1 from 6 to 4 +move 14 from 5 to 6 +move 23 from 3 to 1 +move 2 from 5 to 6 +move 1 from 4 to 2 +move 6 from 5 to 7 +move 16 from 6 to 5 +move 2 from 2 to 6 +move 2 from 6 to 1 +move 2 from 2 to 4 +move 1 from 2 to 8 +move 15 from 1 to 3 +move 4 from 8 to 2 +move 9 from 1 to 8 +move 12 from 5 to 7 +move 2 from 5 to 1 +move 1 from 4 to 6 +move 1 from 5 to 6 +move 3 from 7 to 3 +move 2 from 8 to 6 +move 1 from 2 to 3 +move 2 from 3 to 5 +move 3 from 1 to 9 +move 12 from 3 to 9 +move 4 from 9 to 7 +move 2 from 9 to 5 +move 4 from 8 to 5 +move 8 from 7 to 2 +move 6 from 5 to 8 +move 2 from 5 to 7 +move 12 from 7 to 1 +move 2 from 6 to 7 +move 11 from 2 to 4 +move 1 from 6 to 5 +move 1 from 5 to 8 +move 10 from 8 to 6 +move 7 from 1 to 9 +move 3 from 3 to 8 +move 2 from 7 to 4 +move 1 from 5 to 3 +move 9 from 4 to 7 +move 16 from 9 to 6 +move 2 from 1 to 6 +move 1 from 7 to 8 +move 2 from 4 to 1 +move 1 from 1 to 5 +move 1 from 5 to 7 +move 2 from 3 to 9 +move 5 from 4 to 6 +move 1 from 3 to 6 +move 1 from 4 to 5 +move 1 from 5 to 8 +move 16 from 6 to 5 +move 2 from 7 to 6 +move 21 from 6 to 2 +move 3 from 8 to 7 +move 1 from 9 to 1 +move 7 from 7 to 1 +move 14 from 2 to 5 +move 1 from 9 to 3 +move 1 from 3 to 1 +move 1 from 8 to 3 +move 2 from 2 to 6 +move 15 from 5 to 1 +move 20 from 1 to 8 +move 1 from 3 to 5 +move 4 from 2 to 8 +move 2 from 1 to 2 +move 2 from 6 to 8 +move 3 from 7 to 6 +move 2 from 6 to 7 +move 1 from 7 to 2 +move 6 from 5 to 6 +move 3 from 5 to 9 +move 2 from 9 to 6 +move 1 from 9 to 4 +move 2 from 2 to 3 +move 1 from 3 to 2 +move 2 from 1 to 4 +move 1 from 3 to 9 +move 2 from 4 to 7 +move 4 from 8 to 4 +move 8 from 8 to 6 +move 5 from 6 to 9 +move 6 from 6 to 7 +move 6 from 6 to 3 +move 5 from 3 to 2 +move 2 from 2 to 3 +move 10 from 7 to 1 +move 2 from 5 to 2 +move 2 from 4 to 1 +move 5 from 5 to 9 +move 2 from 3 to 5 +move 2 from 9 to 4 +move 5 from 4 to 8 +move 8 from 9 to 6 +move 16 from 1 to 9 +move 7 from 2 to 7 +move 10 from 9 to 4 +move 10 from 4 to 8 +move 1 from 7 to 3 +move 1 from 2 to 5 +move 3 from 5 to 7 +move 2 from 3 to 6 +move 5 from 7 to 4 +move 4 from 4 to 5 +move 17 from 8 to 3 +move 9 from 6 to 2 +move 17 from 3 to 9 +move 9 from 8 to 3 +move 2 from 5 to 6 +move 1 from 5 to 8 +move 5 from 2 to 4 +move 1 from 6 to 9 +move 3 from 9 to 5 +move 3 from 7 to 4 +move 13 from 9 to 3 +move 3 from 9 to 2 +move 1 from 9 to 8 +move 2 from 6 to 4 +move 9 from 3 to 4 +move 3 from 9 to 3 +move 1 from 8 to 1 +move 2 from 5 to 2 +move 5 from 4 to 7 +move 1 from 9 to 2 +move 6 from 7 to 2 +move 1 from 9 to 6 +move 9 from 2 to 4 +move 1 from 1 to 7 +move 1 from 6 to 5 +move 1 from 7 to 4 +move 4 from 4 to 2 +move 12 from 3 to 6 +move 7 from 2 to 5 +move 1 from 2 to 1 +move 1 from 1 to 9 +move 2 from 2 to 6 +move 5 from 8 to 2 +move 8 from 6 to 3 +move 1 from 9 to 3 +move 4 from 2 to 7 +move 1 from 3 to 2 +move 2 from 2 to 7 +move 1 from 2 to 5 +move 3 from 6 to 3 +move 10 from 5 to 8 +move 1 from 5 to 3 +move 1 from 6 to 5 +move 5 from 8 to 7 +move 1 from 5 to 8 +move 2 from 6 to 3 +move 5 from 7 to 4 +move 3 from 3 to 6 +move 2 from 8 to 6 +move 3 from 8 to 2 +move 1 from 3 to 7 +move 15 from 4 to 5 +move 10 from 4 to 1 +move 7 from 3 to 5 +move 1 from 2 to 9 +move 5 from 5 to 7 +move 8 from 5 to 9 +move 4 from 3 to 6 +move 3 from 9 to 6 +move 3 from 1 to 4 +move 10 from 7 to 4 +move 2 from 2 to 4 +move 2 from 3 to 5 +move 1 from 7 to 2 +move 1 from 7 to 6 +move 6 from 6 to 5 +move 7 from 5 to 3 +move 1 from 8 to 3 +move 5 from 1 to 6 +move 9 from 5 to 3 +move 14 from 4 to 7 +move 1 from 2 to 8 +move 1 from 8 to 2 +move 1 from 6 to 4 +move 2 from 4 to 7 +move 1 from 2 to 9 +move 1 from 4 to 8 +move 2 from 1 to 4 +move 8 from 6 to 1 +move 1 from 4 to 3 +move 1 from 5 to 8 +move 12 from 7 to 3 +move 1 from 4 to 8 +move 7 from 9 to 1 +move 3 from 6 to 2 +move 3 from 8 to 7 +move 1 from 2 to 9 +move 4 from 7 to 1 +move 6 from 1 to 7 +move 2 from 2 to 8 +move 7 from 7 to 3 +move 10 from 1 to 6 +move 20 from 3 to 1 +move 2 from 6 to 7 +move 1 from 9 to 1 +move 8 from 6 to 8 +move 6 from 8 to 9 +move 5 from 3 to 7 +move 2 from 7 to 3 +move 2 from 9 to 2 +move 5 from 1 to 3 +move 2 from 9 to 8 +move 8 from 3 to 7 +move 6 from 8 to 3 +move 1 from 9 to 8 +move 19 from 1 to 6 +move 17 from 3 to 6 +move 2 from 2 to 4 +move 1 from 3 to 5 +move 1 from 4 to 1 +move 1 from 4 to 8 +move 2 from 8 to 5 +move 1 from 5 to 1 +move 1 from 5 to 4 +move 1 from 5 to 7 +move 2 from 1 to 3 +move 15 from 7 to 4 +move 1 from 9 to 7 +move 2 from 7 to 6 +move 21 from 6 to 4 +move 17 from 6 to 8 +move 2 from 3 to 5 +move 29 from 4 to 9 +move 15 from 9 to 7 +move 1 from 5 to 1 +move 9 from 8 to 2 +move 10 from 9 to 3 +move 8 from 2 to 6 diff --git a/days/5/sample.txt b/days/5/sample.txt new file mode 100644 index 0000000..84933bb --- /dev/null +++ b/days/5/sample.txt @@ -0,0 +1,9 @@ + [D] +[N] [C] +[Z] [M] [P] + 1 2 3 + +move 1 from 2 to 1 +move 3 from 1 to 3 +move 2 from 2 to 1 +move 1 from 1 to 2 From 7c2a9d1c34f8b9a90fcaa3eef8349a7fad7759d8 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 5 Dec 2022 19:30:44 +0100 Subject: [PATCH 021/120] Day 5, Task 2: Hanoi, yes? --- days/5/day5.go | 57 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/days/5/day5.go b/days/5/day5.go index 4d852e3..2f5527c 100644 --- a/days/5/day5.go +++ b/days/5/day5.go @@ -29,6 +29,12 @@ func (s *stack) Push(x byte) { s.crates = append(s.crates, x) } +func (s *stack) Clone() stack { + result := stack{} + result.crates = append(result.crates, s.crates...) + return result +} + type action struct { from int to int @@ -47,7 +53,7 @@ var sampleInput string //go:embed input.txt var fullInput string -func simulateActions(stacks []stack, actions []action) error { +func simulateActionsCrateMover9000(stacks []stack, actions []action) error { for _, action := range actions { for i := 0; i < action.count; i++ { x := stacks[action.from - 1].Pop() @@ -57,6 +63,26 @@ func simulateActions(stacks []stack, actions []action) error { return nil } +func simulateActionsCrateMover9001(stacks []stack, actions []action) error { + for _, action := range actions { + if action.count == 1 { + x := stacks[action.from - 1].Pop() + stacks[action.to - 1].Push(x) + } else { + helper := stack{} + for i := 0; i < action.count; i++ { + x := stacks[action.from - 1].Pop() + helper.Push(x) + } + for i := 0; i < action.count; i++ { + x := helper.Pop() + stacks[action.to - 1].Push(x) + } + } + } + return nil +} + func parseAction(l string) (action, error) { var count, from, to int @@ -126,22 +152,39 @@ func parseInput(input string) (stacks []stack, actions []action, err error) { return stacks, actions, nil } +func getTopCrates(stacks []stack) string { + result := "" + for _, stack := range stacks { + result += string(stack.Top()) + } + return result +} + func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) - stacks, actions, err := parseInput(input) + inputStacks, actions, err := parseInput(input) if err != nil { return fmt.Errorf("cannot parse input: %w", err) } - err = simulateActions(stacks, actions) + + stacks := make([]stack, len(inputStacks)) + for i, stack := range inputStacks { + stacks[i] = stack.Clone() + } + err = simulateActionsCrateMover9000(stacks, actions) if err != nil { return fmt.Errorf("cannot simulate actions: %w", err) } + fmt.Printf("Top crates (CrateMover 9000): %s\n", getTopCrates(stacks)) - topCrates := "" - for _, stack := range stacks { - topCrates += string(stack.Top()) + for i, stack := range inputStacks { + stacks[i] = stack.Clone() + } + err = simulateActionsCrateMover9001(stacks, actions) + if err != nil { + return fmt.Errorf("cannot simulate actions: %w", err) } - fmt.Printf("Top crates: %s\n", topCrates) + fmt.Printf("Top crates (CrateMover 9001): %s\n", getTopCrates(stacks)) return nil } From 9a23f26bb2098f9383da4795bb42743c366325ec Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Tue, 6 Dec 2022 08:51:51 +0100 Subject: [PATCH 022/120] Report errors from the `Run` function --- cmd/days.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/days.go b/cmd/days.go index 8aa7f3d..abeca9e 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -32,7 +32,11 @@ func init() { Use: fmt.Sprintf("day%d", index + 1), Short: day.short, Run: func(cmd *cobra.Command, args []string) { - day.run(useSampleInput) + err := day.run(useSampleInput) + if err != nil { + fmt.Printf("Error: %v", err) + os.Exit(1) + } }, } rootCmd.AddCommand(cmd) From 4fbcd67d372b9a040f3c45fde68d87bf2477fbe0 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Tue, 6 Dec 2022 08:59:53 +0100 Subject: [PATCH 023/120] Day 6, Task 1: Signal processing --- .vscode/launch.json | 4 +-- cmd/days.go | 3 +++ days/6/days6.go | 60 +++++++++++++++++++++++++++++++++++++++++++++ days/6/input.txt | 1 + 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 days/6/days6.go create mode 100644 days/6/input.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index e8c7be6..99620f6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "mode": "debug", "request": "launch", "args": [ - "day5", + "day6", "--sample=true" ], "program": "${workspaceFolder}" @@ -21,7 +21,7 @@ "mode": "debug", "request": "launch", "args": [ - "day5", + "day6", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index abeca9e..3e0ee40 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -2,12 +2,14 @@ package cmd import ( "fmt" + "os" day1 "github.com/ankon/adventofcode/2022/days/1" day2 "github.com/ankon/adventofcode/2022/days/2" day3 "github.com/ankon/adventofcode/2022/days/3" day4 "github.com/ankon/adventofcode/2022/days/4" day5 "github.com/ankon/adventofcode/2022/days/5" + day6 "github.com/ankon/adventofcode/2022/days/6" "github.com/spf13/cobra" ) @@ -24,6 +26,7 @@ var days = []day{ {"Rucksack Reorganization", day3.Run}, {"Camp Cleanup", day4.Run}, {"Supply Stacks", day5.Run}, + {"Tuning Trouble", day6.Run}, } func init() { diff --git a/days/6/days6.go b/days/6/days6.go new file mode 100644 index 0000000..3370680 --- /dev/null +++ b/days/6/days6.go @@ -0,0 +1,60 @@ +package _6 + +import ( + _ "embed" + "fmt" +) + +var knownInputs = map[string]int{ + "mjqjpqmgbljsphdztnvjfqwrcgsmlb": 7, + // "bvwbjplbgvbhsrlpgdmjqwftvncz": 5, + // "nppdvjthqldpwncqszvftbrmjlhg": 6, + // "nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg": 10, + // "zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw": 11, +} + +//go:embed input.txt +var fullInput string + +func Run(useSampleInput bool) error { + for input, expectedResult := range knownInputs { + result, err := detectMarker(input) + if err != nil { + return fmt.Errorf("tests failed: %w", err) + } + if result != expectedResult { + return fmt.Errorf("unexpected result for %q: Expected %d, got %d", input, expectedResult, result) + } + } + if useSampleInput { + return nil + } + + index, err := detectMarker(fullInput) + if err != nil { + return fmt.Errorf("failed to detect marker: %w", err) + } + fmt.Printf("Marker after %d\n", index) + + return nil +} + +func isMarker(s string) bool { + for i := 0; i < len(s); i++ { + for j := 0; j < i; j++ { + if s[j] == s[i] { + return false + } + } + } + return true +} + +func detectMarker(input string) (int, error) { + for i := 4; i < len(input); i++ { + if isMarker(input[i-4:i]) { + return i, nil + } + } + return -1, fmt.Errorf("cannot find marker") +} diff --git a/days/6/input.txt b/days/6/input.txt new file mode 100644 index 0000000..51e21b2 --- /dev/null +++ b/days/6/input.txt @@ -0,0 +1 @@ +bfdbbngnvnsvshhhrvrbrtbrrhqrqgrrmmdfmmqttptltntrntrnrcrdcrrctctdtwtrwwmlltcltcllmpprvvtbbmbvbsvvqwvvscswsqqgzqqppvzppnddjwddlrdlllmwllfccdfccswwrhhndhdhfdftdfdcdcllcjjbsbgssvlvrrhfrfjfpjffvnfvfwfzftztwwrhwrhwhwddpjjmhmgmsssstzszqzfqzzprpzpnndttphtpphvvcpcjppdtdwwqgwwwnhwnnvhvsvqqtrrbsscwssgwglgwlldjdzjjbsjbsbvvpbvppvfvqvbqbzzwtwbwpbbbcffdgggpnpfptpfphfhfthfthffzrrbzbcblbmmzmhhnvvqvlvwvzvtztgzznbbcqbccwhcwcnwnhndhhgcghhlthllplvppgngrgsswfsfnfjjswstsrtrhthhqzqggdtggzvvjljddqdzzrmrjmjcmjmrrwlldttrhhfjjgbglgjlldrllppnwpnwnndrddtdqdhhpccbgcgzzswzztgzzrwwzzmtztvvrtrgttvddwvwvmwvmmdjdrdtthqhgqhggldgdfdnnzjnjffmrrnprnpnssjrrbrjjrrzvrvhvllfvlvnlvvhlhrhzrzrsrswrssjvjdjfjwwjmjvjjthhnjnmnppsccmlcclfclcbllldwldwdlwddbddmnmrmgrmmtsszgssqjsqscswwzmwmbwwvqqbtbtwwpbbwdbdbhhqmqgqddflfmfnmffbtfbbsdsffspsjpsspzszccrsrstrtjrjppcrrpqqvttsbbjtbjjpbbccmzznvvzzvnvmmwmhmvmsstlssqtssvggtbgttgvtggfhggbcgcmcrmcmhhbttdlttfrfprrvttrtggcpplccqggcwwdjjjplprrbsrbbjsjbbfhbhphtttpffdgdgjddzldzlzplpnplljttdqqlmlllhzhjhccpwcwhwwbbqtqffjpfpfpjptplltbtzbbwwvggpcpprdprpbpvvgzgczzfffzcfzccjffrmrhmrhhchvhddsvswscsnnpfppdrdcrdrgdgmdgmgllhggjwggvqvmmvrrzpprhhqfhfvffvlvnlngnffbbtccfbfhfwhhhhwcwzwjjbffvrffqrrnsnwswrsrvrjvrvprpsptspttbztzfzlfzlflcflclqlplglmlqqvlvvhccmmddqvqzvvmlllvnlnhnfnwnlndnntrrhvvgjjnpnggfqgqdqqzvvclvclvlfvlvvlzlssqffmrfmfmjjczcmmmnttnfnmfnmmmhmggjgdjjqmjjvsslszlzrrpdpcpfcpfpnpssvtsvtvllbttzzljzzhrrnsnddjgdjgjljzzvhvddmdvvdtdmmpmqmnnwcwfwbfwwsvvbpvvgvnvcvdvtvrrcppwbppcqpccwqqzmqmmzczppwbbrzrjzzcrcvrrpttrjjcdjcjfcclscstthqhfqhffdcfdfqdqldddsswbblppdmdnnjvvhwvhvjhvjhjhlhcclrrcqcgcjgcjjtbtctbcbsccfwwltlrlplpfpjphplhhgtghhrppwhhrprwpwhhdqdpdwpwwtccvncvvvrpvphpssfpplcczttltgltldlmlqmmbsszdszznpprsprsprsppsbppjddjhhnrrfsrffmlmglgmlglccddpssdpsddhhfmfsfrfsfnnlggfrgghmgmrmprmprrnvrnnbqnqddhhfwfmfwfmfpfdfzdzppsbpsbpprfrvvwvtwtltvlttrhhgvhhjttmssdggnzzvmvcczmzbzwzttvtpvpcphcctmmhshjsjbssglsglgtltslscchhhsjjpljjdtdsdpppptlpprmppwdppglgmggnddztdzddzppswwmhfbpqzffjqgmsntwsnrwqrqwgpwgrbpbjwrhbcdcvqjnwslsnwhglcsjbwjhswjvzssfqgwbbdgbwfrblfmmlmsndhtlbwzfwsspqlncspqbgbnzshbwpvrmjqjzbcbzzdgssbtqdzffjphqjvrspfrjhpspbwcjwbfhqzsdnjwqjzjtjgnbrdbwqhzffphzppvlmsmppqcfjbjbdsnbwtvthwqcfrtfrwchnmqmhnwfcjtbwqwwvlnpmwlrvzwljrljzqstzglqwbzfdftzltlcbvmmfwcjqglvznztwnvzvftpndqmngqswppsnqhdbgthrddfbcfpflpndrhmcqwvnbfztsvnjjdwqgpmvdwvdftgbtvrwbnvvrwsdfzhwbwdhlpzbcqdzhbfqtpjqcmrpvcsrmcwvgghqrclfzpfgnppzmhvdhvdfrcrnjbdcwbftcqjhhfdsnfnwjzjllzzqftzsjrqnsbpjdcswhhmwwdzmvmqcjtqnczjcvzmmqwzjhjpcczgpbmcvbwmpmvnghlrgcmrrdnmjvmvnhtpfpgwgmdfzvlbclzjzwdqqcvfhhgfzdhzpdvfmwjlzzrpdgzmttmvvcplbwfzqftcgcwcgcpgwvnmlqsplpqwfnhwvqtlwcspqdzshsqnlcpqhpcpbwdhdjsmvtbqdwbcrscqfjcrcjhbjbpzbshpbmlcthmbjfwhzfphgbfqfnfztptzvdnwrpslmdtpmzmpbsszqshwdghrbtvhwzhcmpcgfqggpgzwmhhdrlhlvnpzvwwhzqvgvhrzngttcnqgjjhnblncnqnjzlwnmwnrtvwjtnrbhthncwmzwqdbdgtwrncljddnbhmphgjzfrrgmmcwfwjwjlcrhvcdtvsrvsfhmlgmzsgjchhrfmqslmdgtdtrlbhdffddvbsdbdwlwdcmcmmpvzpdtmbthjdzlpwftptpfsggmhjfjwvbwljsfhfwtbfwmczwhbmhvzllqtcqqfbrcdqqsrcpfmnswnfzfqghcmcbqwgvzqpwvvmbpddlhgjgzvgmpljznrhqphwcztqzpnhzqdgpwwclmsgpwnwtvtsjsdmcnvmjbqglttrhbzqdbgwnbsqzmsmztndrtmlpszhzgjbbftbsdwwdrlftrbbnrsqshfhdpdrwmztcqzdjlnthnjhppwntmbqdgzpmfmfnccblsdwljqhjfgtlgvpzpjbsndmwzfwrbmdhpnmbchqlwqtbhhhqqbsfnvscjwrzvjdtvbsqwzvfhwbbjgqpzcwqjdrlfmggzmhbcrhtbqdjntbtqdvmvpqflmccfpnbmnmtqbdflsgczpbsqpfphlzqgvwbjlmsgshrhpcljzdvwvdvlqqwchtjmjgtqjhgwtnddmhphwhvwhtrhfbjjjzfgrcqngnnddctzdzlqjlbdwmjqzccwrvctrzgtzqsswggbqdnplclhtdslcvzhppcjjslnshtwjnbrwdprqhdtfqmqpgfgnqtdnnhrnzfrsqhlftpdslgmmvqhvpjqjwpwgtnmgrbhwntdjftfwtjzjtprctbtsjmqmpcbbtrjvsgqgsfjprqmsmdztbhnbgzldqfzgwqwnnccgcfclctrwqmqpgvfglgsmmpjszqnphnzcnvswpsfsrmnsnlqnpmvfdvdtfgzrdmbftdrrrbfsvzfgmnffvjpcpnndrwhtjjrrvnztlfhcvfqjgfrhtbnhmwnrmwdhzmmtvjmsqmghtbtfjwdnvdcqtqjrfhrwscjftmbgjmcsrbpdpttlmvfmnfjhnptqvggnshzqnlqqdpqqsqssppbwpblhgfrwrblpzwvqphpsgfmbpqtqqpjpgnbblzstgcjhqntgpbfwlzzctqbnbvpgwsdsdldqzhvznqcsrrghpwllshqpdlqnqgzfwrnhwsvhftzplspcbqmclplprlthvwjhdndrjblqdgwvgjlbmblbmcnbzwzdlnpnhhppvrtngvqqwsttgwlvtcqmtrvpbnvcnfqdtqrsrsmhclmtgbdwwdvhwgfcqpmprcpdhqwftcchbwvstcdqrlwtgbcfqfgzprgvpbbzlqfzbqtcrlzscnqpqwtgzbbbdvsvmhggdr From 656d434e05b337723f01d315e71da10df288f6e4 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Tue, 6 Dec 2022 09:06:38 +0100 Subject: [PATCH 024/120] Day 6, Task 2: Longer signals This seems to mark the inflection point, where we will work on a bigger puzzle over multiple days. There will be more refactoring in the framework ... --- days/6/days6.go | 54 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/days/6/days6.go b/days/6/days6.go index 3370680..f3fdb23 100644 --- a/days/6/days6.go +++ b/days/6/days6.go @@ -5,12 +5,23 @@ import ( "fmt" ) -var knownInputs = map[string]int{ - "mjqjpqmgbljsphdztnvjfqwrcgsmlb": 7, - // "bvwbjplbgvbhsrlpgdmjqwftvncz": 5, - // "nppdvjthqldpwncqszvftbrmjlhg": 6, - // "nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg": 10, - // "zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw": 11, +type expected struct { + packet int + message int +} + +type requiredLength int +const ( + startOfPacket requiredLength = 4 + startOfMessage requiredLength = 14 +) + +var knownInputs = map[string]expected{ + "mjqjpqmgbljsphdztnvjfqwrcgsmlb": {7, 19}, + "bvwbjplbgvbhsrlpgdmjqwftvncz": {5, 23}, + "nppdvjthqldpwncqszvftbrmjlhg": {6, 23}, + "nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg": {10, 29}, + "zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw": {11, 26}, } //go:embed input.txt @@ -18,23 +29,36 @@ var fullInput string func Run(useSampleInput bool) error { for input, expectedResult := range knownInputs { - result, err := detectMarker(input) + result, err := detectMarker(input, startOfPacket) if err != nil { return fmt.Errorf("tests failed: %w", err) } - if result != expectedResult { - return fmt.Errorf("unexpected result for %q: Expected %d, got %d", input, expectedResult, result) + if result != expectedResult.packet { + return fmt.Errorf("unexpected start-of-packet marker for %q: Expected %d, got %d", input, expectedResult.packet, result) + } + result, err = detectMarker(input, startOfMessage) + if err != nil { + return fmt.Errorf("tests failed: %w", err) + } + if result != expectedResult.message { + return fmt.Errorf("unexpected start-of-message marker for %q: Expected %d, got %d", input, expectedResult.message, result) } } if useSampleInput { return nil } - index, err := detectMarker(fullInput) + index, err := detectMarker(fullInput, startOfPacket) + if err != nil { + return fmt.Errorf("failed to detect start-of-packet marker: %w", err) + } + fmt.Printf("start-of-packet marker after %d\n", index) + + index, err = detectMarker(fullInput, startOfMessage) if err != nil { - return fmt.Errorf("failed to detect marker: %w", err) + return fmt.Errorf("failed to detect start-of-message marker: %w", err) } - fmt.Printf("Marker after %d\n", index) + fmt.Printf("start-of-message marker after %d\n", index) return nil } @@ -50,9 +74,9 @@ func isMarker(s string) bool { return true } -func detectMarker(input string) (int, error) { - for i := 4; i < len(input); i++ { - if isMarker(input[i-4:i]) { +func detectMarker(input string, t requiredLength) (int, error) { + for i := int(t); i < len(input); i++ { + if isMarker(input[i-int(t):i]) { return i, nil } } From 69dcb7084c725dfc2460ae811ba733404e957503 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Wed, 7 Dec 2022 21:44:08 +0100 Subject: [PATCH 025/120] Align naming of the file with the rest of the repo --- days/6/{days6.go => day6.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename days/6/{days6.go => day6.go} (100%) diff --git a/days/6/days6.go b/days/6/day6.go similarity index 100% rename from days/6/days6.go rename to days/6/day6.go From a1c599ba985a86ff4a99cf98dc21680102889822 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Wed, 7 Dec 2022 22:56:42 +0100 Subject: [PATCH 026/120] Day 7, Task ... 0: Parse the input. --- .vscode/launch.json | 4 +- cmd/days.go | 2 + days/7/day7.go | 152 +++++++ days/7/input.txt | 1046 +++++++++++++++++++++++++++++++++++++++++++ days/7/sample.txt | 23 + 5 files changed, 1225 insertions(+), 2 deletions(-) create mode 100644 days/7/day7.go create mode 100644 days/7/input.txt create mode 100644 days/7/sample.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index 99620f6..b620041 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "mode": "debug", "request": "launch", "args": [ - "day6", + "day7", "--sample=true" ], "program": "${workspaceFolder}" @@ -21,7 +21,7 @@ "mode": "debug", "request": "launch", "args": [ - "day6", + "day7", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index 3e0ee40..6e15cfa 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -10,6 +10,7 @@ import ( day4 "github.com/ankon/adventofcode/2022/days/4" day5 "github.com/ankon/adventofcode/2022/days/5" day6 "github.com/ankon/adventofcode/2022/days/6" + day7 "github.com/ankon/adventofcode/2022/days/7" "github.com/spf13/cobra" ) @@ -27,6 +28,7 @@ var days = []day{ {"Camp Cleanup", day4.Run}, {"Supply Stacks", day5.Run}, {"Tuning Trouble", day6.Run}, + {"No Space Left On Device", day7.Run}, } func init() { diff --git a/days/7/day7.go b/days/7/day7.go new file mode 100644 index 0000000..4ac3c9c --- /dev/null +++ b/days/7/day7.go @@ -0,0 +1,152 @@ +package _7 + +import ( + _ "embed" + "fmt" + "strconv" + "strings" + + "github.com/ankon/adventofcode/2022/days" +) + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +type ftype int32 + +const ( + file ftype = iota + dir +) + +type direntry struct { + ftype ftype + size int + name string + + children []direntry + parent *direntry +} + +func readDir(parent *direntry, lines []string) ([]direntry, int, error) { + entries := []direntry{} + i := 0 + for i = 0; i < len(lines); i++ { + if lines[i] == "" { + break + } + + s, name, found := strings.Cut(lines[i], " ") + if !found { + return []direntry{}, -1, fmt.Errorf("invalid ls output %q", lines[i]) + } + if s == "$" { + break + } + + var ftype ftype + var size int + if s == "dir" { + ftype = dir + } else { + ftype = file + tmp, err := strconv.Atoi(s) + if err != nil { + return []direntry{}, -1, err + } + size = tmp + } + entries = append(entries, direntry{ + ftype, + size, + name, + []direntry{}, + parent, + }) + } + + return entries, i, nil +} + +func loadFS(input string) (root direntry, err error) { + root = direntry{ + ftype: dir, + size: 0, + name: "/", + children: []direntry{}, + } + cwd := &root + lines := strings.Split(input, "\n") + for i := 0; i < len(lines); i++ { + cmd := lines[i] + if cmd == "" { + continue + } + + p := strings.Split(cmd, " ") + if p[0] != "$" { + return direntry{}, fmt.Errorf("command expected") + } + + switch p[1] { + case "cd": + name := p[2] + if name == "/" { + cwd = &root + } else if name == ".." { + cwd = cwd.parent + } else { + var ncwd *direntry + for i := 0; i < len(cwd.children); i++ { + if cwd.children[i].name == name { + ncwd = &cwd.children[i] + break + } + } + if ncwd == nil { + return direntry{}, fmt.Errorf("no such directory %q", name) + } + cwd = ncwd + } + case "ls": + entries, count, err := readDir(cwd, lines[i+1:]) + if err != nil { + return direntry{}, err + } + cwd.children = append(cwd.children, entries...) + i += count + default: + return direntry{}, fmt.Errorf("unknown command %q", p[0]) + } + } + + return root, nil +} + +func printDir(de *direntry, indent int) { + fmt.Printf("%*s %8s\n", indent, "", de.name) + for _, child := range de.children { + switch child.ftype { + case dir: + printDir(&child, indent+2) + case file: + fmt.Printf("%*s %8s %d\n", indent+2, "", child.name, child.size) + default: + panic("huh?") + } + } +} + +func Run(useSampleInput bool) error { + input := days.PickInput(useSampleInput, sampleInput, fullInput) + root, err := loadFS(input) + if err != nil { + return err + } + printDir(&root, 0) + + return nil +} diff --git a/days/7/input.txt b/days/7/input.txt new file mode 100644 index 0000000..3c46e58 --- /dev/null +++ b/days/7/input.txt @@ -0,0 +1,1046 @@ +$ cd / +$ ls +149291 cgc.vzv +dir cmcrzdt +dir hwdvrrp +26925 hwqvsl +dir lsmv +dir ngfllcq +dir ngnzzmpc +dir pwhjps +dir rgwnzttf +260556 tcglclw.hsn +dir trvznjhb +dir wgcqrc +68873 whpnhm +$ cd cmcrzdt +$ ls +dir chqllfw +95243 hjpf +108868 hwqvsl +115004 jpppczvz.mtp +dir lnsgfnbr +dir pdtjlb +dir rqfzvwts +dir trvznjhb +$ cd chqllfw +$ ls +56623 cgs.hbt +134804 zqb.grc +$ cd .. +$ cd lnsgfnbr +$ ls +dir jtzw +dir ngfllcq +dir sdm +dir wlsg +$ cd jtzw +$ ls +dir nfz +$ cd nfz +$ ls +255427 hwqvsl +94147 tmnjbqq.fzh +$ cd .. +$ cd .. +$ cd ngfllcq +$ ls +110661 cdgqtwcv.lzn +208050 dpf +$ cd .. +$ cd sdm +$ ls +dir dhwm +dir ngfllcq +125983 rfdz.vqm +24227 tzn +41909 tzn.vnr +dir zdzq +$ cd dhwm +$ ls +dir clr +dir lhv +dir ncvmgn +212499 ngfllcq.dcr +191108 nggnj +dir pdtjlb +dir pwhjps +dir sqqbthdp +dir trvznjhb +$ cd clr +$ ls +dir lnbc +87079 npwhncc +109530 pfqhpr.tzl +249566 tmnjbqq.fzh +dir zgmgztcd +$ cd lnbc +$ ls +62635 ftshngp.vbj +$ cd .. +$ cd zgmgztcd +$ ls +149111 pwhjps.fjm +$ cd .. +$ cd .. +$ cd lhv +$ ls +dir phzfwl +$ cd phzfwl +$ ls +dir gmzcjzm +$ cd gmzcjzm +$ ls +263161 vsptqdv +$ cd .. +$ cd .. +$ cd .. +$ cd ncvmgn +$ ls +245840 hjpf +21272 pbcjtbg +dir stm +$ cd stm +$ ls +dir hnbrd +$ cd hnbrd +$ ls +102906 lftjtq.gdt +45082 vsptqdv +$ cd .. +$ cd .. +$ cd .. +$ cd pdtjlb +$ ls +171382 hwqvsl +$ cd .. +$ cd pwhjps +$ ls +75342 cgc.vzv +185458 hwqvsl +254359 ngfllcq.jzd +dir pdtjlb +200999 slnlws.sgh +91174 vqqbcb +dir zmc +$ cd pdtjlb +$ ls +39001 ngfllcq +$ cd .. +$ cd zmc +$ ls +dir cjqmc +$ cd cjqmc +$ ls +257668 ctsfdprp +889 mzr.hnp +$ cd .. +$ cd .. +$ cd .. +$ cd sqqbthdp +$ ls +154217 pwhjps.jtn +$ cd .. +$ cd trvznjhb +$ ls +105431 hwqvsl +$ cd .. +$ cd .. +$ cd ngfllcq +$ ls +183850 dcppzj.lmm +131039 hbpn.zlp +110398 hjpf +dir pwhjps +251784 rqgslj.sqg +dir szqf +150728 vsptqdv +$ cd pwhjps +$ ls +dir pzrtwv +156616 rpbh.ftj +dir tzn +$ cd pzrtwv +$ ls +197890 tzn +$ cd .. +$ cd tzn +$ ls +121296 pdtjlb.nmg +$ cd .. +$ cd .. +$ cd szqf +$ ls +dir ngfllcq +dir qtrhn +$ cd ngfllcq +$ ls +dir vnfcczg +$ cd vnfcczg +$ ls +86691 cgc.vzv +189290 hjds.lwf +230265 hwqvsl +dir jbmvmzn +223129 ngfllcq.mdw +dir rpcbpjvm +215119 tmnjbqq.fzh +$ cd jbmvmzn +$ ls +dir flrszsrr +175047 hjpf +dir jrzf +dir ngfllcq +$ cd flrszsrr +$ ls +163007 zdvfmqr.pfq +$ cd .. +$ cd jrzf +$ ls +32641 qbnz +$ cd .. +$ cd ngfllcq +$ ls +dir dlcvcd +dir gcpftfm +183962 tzn.mjh +$ cd dlcvcd +$ ls +260612 mhf +$ cd .. +$ cd gcpftfm +$ ls +227489 hwqvsl +$ cd .. +$ cd .. +$ cd .. +$ cd rpcbpjvm +$ ls +dir tnwzgrvw +$ cd tnwzgrvw +$ ls +dir trvznjhb +$ cd trvznjhb +$ ls +127767 pdtjlb.qjw +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd qtrhn +$ ls +81716 dngdll +76367 tdj +180116 tmnjbqq.fzh +$ cd .. +$ cd .. +$ cd .. +$ cd zdzq +$ ls +192339 bqcmzm.vzw +dir cplvj +dir drpmlmf +92165 mcthl.dzw +dir qccnln +$ cd cplvj +$ ls +dir gmqddf +71720 hjpf +220700 hwqvsl +260353 lgw.msr +$ cd gmqddf +$ ls +36587 dmdgjrs +$ cd .. +$ cd .. +$ cd drpmlmf +$ ls +4896 hjpf +dir ngfllcq +65712 pwhjps.mng +67097 tmnjbqq.fzh +$ cd ngfllcq +$ ls +248967 swvf.prt +$ cd .. +$ cd .. +$ cd qccnln +$ ls +dir tzn +$ cd tzn +$ ls +81833 vsptqdv +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd wlsg +$ ls +181214 nmglzcds.hcg +195698 pdtjlb.vbr +dir trvznjhb +77162 vsptqdv +$ cd trvznjhb +$ ls +237856 trvznjhb +$ cd .. +$ cd .. +$ cd .. +$ cd pdtjlb +$ ls +101237 hwqvsl +dir jssl +dir ngfllcq +dir pvlqvdrw +dir pwhjps +dir tzn +115255 vsptqdv +$ cd jssl +$ ls +76335 smmjjrp +$ cd .. +$ cd ngfllcq +$ ls +102639 cgc.vzv +55243 fjfhdtr.ltc +$ cd .. +$ cd pvlqvdrw +$ ls +38570 pwhjps.qgq +191322 scnbjgg.gww +$ cd .. +$ cd pwhjps +$ ls +dir ghfwwj +dir vtr +$ cd ghfwwj +$ ls +109461 mdtp.ztw +$ cd .. +$ cd vtr +$ ls +dir fmtpdc +$ cd fmtpdc +$ ls +42101 bcdbqcs.lhp +$ cd .. +$ cd .. +$ cd .. +$ cd tzn +$ ls +dir pdtjlb +$ cd pdtjlb +$ ls +154813 vsptqdv +$ cd .. +$ cd .. +$ cd .. +$ cd rqfzvwts +$ ls +250112 hwqvsl +63241 tzn +149460 tzn.pph +$ cd .. +$ cd trvznjhb +$ ls +784 bdptcbl.ntt +108339 cgc.vzv +dir hnpdrdsm +dir mnnwcmd +dir ngfllcq +dir pbsnd +dir pdtjlb +261083 rhl.cjh +dir trvznjhb +103421 wjftfs +$ cd hnpdrdsm +$ ls +253895 pwhjps.nps +36928 ssjhl +235679 tmnjbqq.fzh +38049 trvznjhb.dzs +$ cd .. +$ cd mnnwcmd +$ ls +218411 fvzhntq.rwm +78694 gwlcbbtm +243270 hjpf +15610 trvznjhb.wdj +$ cd .. +$ cd ngfllcq +$ ls +dir fmhlq +dir fwbdttbj +dir hccstwh +$ cd fmhlq +$ ls +142240 rbrwv.hjl +dir tjpwvb +256604 tmnjbqq.fzh +dir trvznjhb +$ cd tjpwvb +$ ls +83436 sfrpt +$ cd .. +$ cd trvznjhb +$ ls +44433 trvznjhb +$ cd .. +$ cd .. +$ cd fwbdttbj +$ ls +4127 hwqvsl +$ cd .. +$ cd hccstwh +$ ls +dir cbd +243765 lvzsrqlw.llc +$ cd cbd +$ ls +158372 vzgtjqbd.tmd +$ cd .. +$ cd .. +$ cd .. +$ cd pbsnd +$ ls +172548 cgc.vzv +261836 pwhjps +$ cd .. +$ cd pdtjlb +$ ls +73184 cgc.vzv +dir mdbjwvh +dir mgt +dir nbrvvghc +98702 ngf.gtb +dir ngfllcq +224788 pdtjlb +191754 tmnjbqq.fzh +189444 tnqwbmzm.vlq +dir tzn +dir ztzsg +$ cd mdbjwvh +$ ls +135602 nvt.rjh +$ cd .. +$ cd mgt +$ ls +dir pbrtf +dir whflvwv +$ cd pbrtf +$ ls +dir tnnnllg +$ cd tnnnllg +$ ls +269436 hjpf +$ cd .. +$ cd .. +$ cd whflvwv +$ ls +185562 ngfllcq +dir rdl +150984 trvznjhb +$ cd rdl +$ ls +231952 mqjcttf +$ cd .. +$ cd .. +$ cd .. +$ cd nbrvvghc +$ ls +dir pdtjlb +$ cd pdtjlb +$ ls +40347 hjpf +dir vwl +$ cd vwl +$ ls +124408 tzn.hjw +$ cd .. +$ cd .. +$ cd .. +$ cd ngfllcq +$ ls +54894 bvgf +$ cd .. +$ cd tzn +$ ls +41506 vnhlvqqw.cvd +$ cd .. +$ cd ztzsg +$ ls +216433 fzsnpr.vrd +dir grrngq +dir hcmvbhp +dir lbmnq +19985 ngfllcq +dir pqqjgbvj +dir zsnggz +$ cd grrngq +$ ls +dir cqcvb +dir ngfllcq +dir shrhb +$ cd cqcvb +$ ls +125712 cgc.vzv +69800 fpszwd +160009 rbbwsszz +dir trvznjhb +33640 tzghd.fjp +$ cd trvznjhb +$ ls +dir gtjfll +dir mrncfvnp +dir pwt +dir trvznjhb +173974 tzn +$ cd gtjfll +$ ls +126840 cgc.vzv +180163 fswwvhwn +dir gnpcbvmt +122192 ngfllcq.snb +$ cd gnpcbvmt +$ ls +127188 crhvwb.pct +218972 mwg +$ cd .. +$ cd .. +$ cd mrncfvnp +$ ls +216569 phlbdl +$ cd .. +$ cd pwt +$ ls +119692 tmnjbqq.fzh +$ cd .. +$ cd trvznjhb +$ ls +203464 nltqsvd.fhc +$ cd .. +$ cd .. +$ cd .. +$ cd ngfllcq +$ ls +31226 rdwczp.hfq +$ cd .. +$ cd shrhb +$ ls +246035 bnbg +98513 hjpf +$ cd .. +$ cd .. +$ cd hcmvbhp +$ ls +dir cbb +201230 cgc.vzv +dir grmmpz +220707 hjpf +dir jnr +dir psv +dir trvznjhb +134184 trvznjhb.ghp +228507 vsptqdv +$ cd cbb +$ ls +17897 hwqvsl +$ cd .. +$ cd grmmpz +$ ls +214171 spsnch.drs +$ cd .. +$ cd jnr +$ ls +82130 bhjqplbc.rth +$ cd .. +$ cd psv +$ ls +215898 pwhjps +$ cd .. +$ cd trvznjhb +$ ls +dir dfcn +98111 gwt.fmw +20948 hjpf +dir pwhjps +dir rnlrgd +$ cd dfcn +$ ls +dir fqm +179114 mbcrjb +dir trvznjhb +dir vfrrzdb +$ cd fqm +$ ls +dir frgwsrdh +$ cd frgwsrdh +$ ls +142027 hhpwsl +$ cd .. +$ cd .. +$ cd trvznjhb +$ ls +dir nbbb +34253 ngfllcq.src +dir qgqmmvg +dir tfgwmlc +11919 trvznjhb.qgz +dir tzn +24383 zvfzhb.dcw +$ cd nbbb +$ ls +260947 pwhjps.bdq +$ cd .. +$ cd qgqmmvg +$ ls +67028 wjvhq.tdz +$ cd .. +$ cd tfgwmlc +$ ls +dir rmcgqpb +dir wdtmdtz +$ cd rmcgqpb +$ ls +263786 nsmcndc.bjs +$ cd .. +$ cd wdtmdtz +$ ls +37751 lnspfqv.tpp +$ cd .. +$ cd .. +$ cd tzn +$ ls +265035 nqsgm.dhm +$ cd .. +$ cd .. +$ cd vfrrzdb +$ ls +dir pzbtsnd +dir srpdb +$ cd pzbtsnd +$ ls +72770 pdtjlb +$ cd .. +$ cd srpdb +$ ls +231540 dzgsf +dir ngfllcq +dir sjv +$ cd ngfllcq +$ ls +26488 cgc.vzv +195815 dfjss +119177 lbjtjqr +$ cd .. +$ cd sjv +$ ls +225677 msgjj +228113 ngfllcq +92448 tzn.rbp +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd pwhjps +$ ls +171613 nzqd.rzh +$ cd .. +$ cd rnlrgd +$ ls +132964 hjpf +146636 hwqvsl +187596 mlrllbbb.wmh +92535 trvznjhb +$ cd .. +$ cd .. +$ cd .. +$ cd lbmnq +$ ls +142963 qfpjgvll.ncb +$ cd .. +$ cd pqqjgbvj +$ ls +dir dfhhzwp +253570 jjbr.cgf +dir lchljrwb +dir pdtjlb +$ cd dfhhzwp +$ ls +dir bqp +$ cd bqp +$ ls +122939 hjpf +$ cd .. +$ cd .. +$ cd lchljrwb +$ ls +259475 fqmppdtd.tjm +$ cd .. +$ cd pdtjlb +$ ls +199658 vsptqdv +$ cd .. +$ cd .. +$ cd zsnggz +$ ls +117242 hjpf +$ cd .. +$ cd .. +$ cd .. +$ cd trvznjhb +$ ls +dir bgvqct +160709 dtq +dir fldlwj +dir ndq +221408 tmnjbqq.fzh +69148 zvfzt.rjm +$ cd bgvqct +$ ls +66024 cmjrmfn.lpt +40153 fdlvqgn.dbt +135848 tmnjbqq.fzh +$ cd .. +$ cd fldlwj +$ ls +172275 ngfllcq.gbb +$ cd .. +$ cd ndq +$ ls +117311 bbhlcn.qll +dir dtzmzgw +123263 hsb +dir jnthg +111208 pdtjlb +200860 pjq +$ cd dtzmzgw +$ ls +dir tzn +$ cd tzn +$ ls +249561 pszf.zcn +$ cd .. +$ cd .. +$ cd jnthg +$ ls +17013 pwhjps.gpp +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd hwdvrrp +$ ls +dir fgvqft +dir fwc +dir sfhsb +dir tzn +dir wbtf +$ cd fgvqft +$ ls +215710 wzh +$ cd .. +$ cd fwc +$ ls +184576 dmvqc.tsr +dir hgznwf +dir lfjtqz +dir ngfllcq +53748 ngfllcq.vgl +dir pgpvcp +$ cd hgznwf +$ ls +51012 tmnjbqq.fzh +$ cd .. +$ cd lfjtqz +$ ls +96666 fwttv.qrp +203264 nhc.lgd +dir pwhjps +213570 tzn +$ cd pwhjps +$ ls +69941 frqq.jnv +136814 pqmsc.dgz +185821 rww.trv +$ cd .. +$ cd .. +$ cd ngfllcq +$ ls +97361 zcw.zrq +$ cd .. +$ cd pgpvcp +$ ls +834 nwv.mtw +$ cd .. +$ cd .. +$ cd sfhsb +$ ls +78513 pdtjlb +$ cd .. +$ cd tzn +$ ls +dir lpf +$ cd lpf +$ ls +242317 bngfvvgq.ptp +82304 ngfllcq.qdz +dir wsvqtcb +$ cd wsvqtcb +$ ls +32176 vrwlnphn.nnv +$ cd .. +$ cd .. +$ cd .. +$ cd wbtf +$ ls +53446 jvvdpn +41661 ngfllcq.vhl +dir pwhjps +231151 tzn +241080 vdzdhdtb.dgj +dir vlqmz +$ cd pwhjps +$ ls +200296 hdds.lsw +$ cd .. +$ cd vlqmz +$ ls +166538 pwhjps.mnq +$ cd .. +$ cd .. +$ cd .. +$ cd lsmv +$ ls +dir dtjjv +87897 hjpf +216417 hwqvsl +dir ngfllcq +dir pdtjlb +dir qlnlbcdv +230724 vsptqdv +177119 vvzvnn +$ cd dtjjv +$ ls +218742 hjpf +$ cd .. +$ cd ngfllcq +$ ls +38560 cgc.vzv +257037 fbttg.jlc +29948 pwhjps.bvj +1253 trvznjhb.nzl +241388 tzn.vdb +dir wlmtj +$ cd wlmtj +$ ls +51957 hjpf +27480 pwhjps.hgj +dir qdjfgz +dir shb +182077 tclmtwh.wzr +dir trvznjhb +103119 twlf.rnl +31950 tzn.zfm +$ cd qdjfgz +$ ls +238882 hpms.gll +dir qpbsmmp +184633 trvznjhb.nsb +130374 vsptqdv +$ cd qpbsmmp +$ ls +60269 spsbz +$ cd .. +$ cd .. +$ cd shb +$ ls +140111 vsptqdv +$ cd .. +$ cd trvznjhb +$ ls +dir qjqzppj +$ cd qjqzppj +$ ls +203246 hjpf +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd pdtjlb +$ ls +41982 hjpf +245930 hwqvsl +dir mmnhtmr +42314 ngfllcq.tcn +68269 pdtjlb +103066 vhtjp.grt +$ cd mmnhtmr +$ ls +dir zqjjgvj +$ cd zqjjgvj +$ ls +263209 nvhflpng.ngd +$ cd .. +$ cd .. +$ cd .. +$ cd qlnlbcdv +$ ls +dir jmd +58921 pdtjlb.mwb +dir pzjgmm +dir qqvrvcw +79958 rrqmn.zwv +18158 swjpt.trv +dir trvznjhb +dir tzn +92135 zjb.nns +268795 zspzsb.szp +$ cd jmd +$ ls +137766 pwhjps +$ cd .. +$ cd pzjgmm +$ ls +1704 tzn.rhf +66307 tzn.zll +116623 vrfvctv.clb +$ cd .. +$ cd qqvrvcw +$ ls +179302 zrqf.fcn +$ cd .. +$ cd trvznjhb +$ ls +265026 qfzlgccf.hvz +dir rbbmmcc +$ cd rbbmmcc +$ ls +dir rtr +$ cd rtr +$ ls +dir dtw +$ cd dtw +$ ls +249472 svs.tgj +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd tzn +$ ls +80112 pdtjlb.thm +$ cd .. +$ cd .. +$ cd .. +$ cd ngfllcq +$ ls +228868 ggcfwgr.mwh +10205 gztwg.pwz +136188 hjpf +141381 hwqvsl +250522 pdtjlb.dwg +dir pwhjps +dir qcwvfl +dir tzn +dir zgwcwqr +$ cd pwhjps +$ ls +19881 tmrljtw +$ cd .. +$ cd qcwvfl +$ ls +63317 fcjsw.jcj +dir gvvfsq +272464 lvqc +148216 nwppjnwc.sdg +121107 tzn.ppw +dir vwfb +$ cd gvvfsq +$ ls +80607 jplds.mjz +$ cd .. +$ cd vwfb +$ ls +dir gtlfdvjz +$ cd gtlfdvjz +$ ls +228623 jbbplpz +dir shf +$ cd shf +$ ls +120966 cgc.vzv +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd tzn +$ ls +215528 cgc.vzv +112331 gtzcl.rzp +128653 mqd.dcz +dir ngfllcq +dir vmfgbzmw +$ cd ngfllcq +$ ls +207193 qchb.hmv +$ cd .. +$ cd vmfgbzmw +$ ls +16152 vtlgffn +$ cd .. +$ cd .. +$ cd zgwcwqr +$ ls +dir pdtjlb +110033 vsptqdv +$ cd pdtjlb +$ ls +9746 cgc.vzv +8010 jdvjpps +$ cd .. +$ cd .. +$ cd .. +$ cd ngnzzmpc +$ ls +116647 gmsnm +157873 hwqvsl +$ cd .. +$ cd pwhjps +$ ls +96321 cgc.vzv +dir lcds +dir tzn +$ cd lcds +$ ls +134975 wcfv.gpd +$ cd .. +$ cd tzn +$ ls +95149 hjpf +55950 pwhjps.rpq +166540 tdt.pgw +236704 trvznjhb.ccn +$ cd .. +$ cd .. +$ cd rgwnzttf +$ ls +122721 hjpf +$ cd .. +$ cd trvznjhb +$ ls +106424 zvqz +$ cd .. +$ cd wgcqrc +$ ls +87367 hjpf +63133 lld +234148 pwhjps.lcr +dir rjnnz +19538 tzn +233765 zlvznnwj +$ cd rjnnz +$ ls +258856 gpgdm diff --git a/days/7/sample.txt b/days/7/sample.txt new file mode 100644 index 0000000..09a921e --- /dev/null +++ b/days/7/sample.txt @@ -0,0 +1,23 @@ +$ cd / +$ ls +dir a +14848514 b.txt +8504156 c.dat +dir d +$ cd a +$ ls +dir e +29116 f +2557 g +62596 h.lst +$ cd e +$ ls +584 i +$ cd .. +$ cd .. +$ cd d +$ ls +4060174 j +8033020 d.log +5626152 d.ext +7214296 k From 7b57641e1c1f65d25217cd62c54241acfff36c80 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 8 Dec 2022 08:32:02 +0100 Subject: [PATCH 027/120] Improve readability of the `printDir` output --- days/7/day7.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/days/7/day7.go b/days/7/day7.go index 4ac3c9c..39817c5 100644 --- a/days/7/day7.go +++ b/days/7/day7.go @@ -127,13 +127,13 @@ func loadFS(input string) (root direntry, err error) { } func printDir(de *direntry, indent int) { - fmt.Printf("%*s %8s\n", indent, "", de.name) + fmt.Printf("%*s- %s\n", indent, "", de.name) for _, child := range de.children { switch child.ftype { case dir: printDir(&child, indent+2) case file: - fmt.Printf("%*s %8s %d\n", indent+2, "", child.name, child.size) + fmt.Printf("%*s- %s (size=%d)\n", indent+2, "", child.name, child.size) default: panic("huh?") } From af8b4a6745778b2746eb1bc8ab4d90111b3313c7 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 8 Dec 2022 08:32:21 +0100 Subject: [PATCH 028/120] Day 7, Task 1: Find candidates --- days/7/day7.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/days/7/day7.go b/days/7/day7.go index 39817c5..b92e983 100644 --- a/days/7/day7.go +++ b/days/7/day7.go @@ -140,6 +140,37 @@ func printDir(de *direntry, indent int) { } } +func calculateDirSizes(de *direntry) int { + size := 0 + for i := 0; i < len(de.children); i++ { + child := &de.children[i] + if child.ftype == dir { + size += calculateDirSizes(child) + } else { + size += child.size + } + } + de.size = size + return size +} + +func findSumOfDirsWithSizeLessThan100K(de *direntry) int { + result := 0 + + for i := 0; i < len(de.children); i++ { + child := &de.children[i] + if child.ftype == file { + continue + } + + if child.size < 100000 { + result += child.size + } + result += findSumOfDirsWithSizeLessThan100K(child) + } + return result +} + func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) root, err := loadFS(input) @@ -148,5 +179,11 @@ func Run(useSampleInput bool) error { } printDir(&root, 0) + totalSize := calculateDirSizes(&root) + fmt.Printf("total size %d\n", totalSize) + + sum := findSumOfDirsWithSizeLessThan100K(&root) + fmt.Printf("sum of sizes of dirs < 100000: %d\n", sum) + return nil } From f6e4f18bc68c7478b83462850b148f02610b05f8 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 8 Dec 2022 08:45:23 +0100 Subject: [PATCH 029/120] Day 7, Task 2: Pick one --- days/7/day7.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/days/7/day7.go b/days/7/day7.go index b92e983..fefe94e 100644 --- a/days/7/day7.go +++ b/days/7/day7.go @@ -15,6 +15,9 @@ var sampleInput string //go:embed input.txt var fullInput string +const totalDiskSpace = 70000000 +const requiredUnusedDiskSpace = 30000000 + type ftype int32 const ( @@ -171,6 +174,32 @@ func findSumOfDirsWithSizeLessThan100K(de *direntry) int { return result } +func findSmallestDirectoryWithSizeLargerThan(de *direntry, minSize int) *direntry { + var result *direntry + for i := 0; i < len(de.children); i++ { + child := &de.children[i] + if child.ftype == file { + continue + } + if child.size < minSize { + // Too small, and won't get bigger + continue + } + + // This directory might work, see whether we can just + // delete a part of it. + better := findSmallestDirectoryWithSizeLargerThan(child, minSize) + if better == nil { + // Nope, the whole thing needs to go. + better = child + } + if result == nil || result.size > better.size { + result = better + } + } + return result +} + func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) root, err := loadFS(input) @@ -185,5 +214,12 @@ func Run(useSampleInput bool) error { sum := findSumOfDirsWithSizeLessThan100K(&root) fmt.Printf("sum of sizes of dirs < 100000: %d\n", sum) + requiredCleanupSize := requiredUnusedDiskSpace - (totalDiskSpace - totalSize) + toDelete := findSmallestDirectoryWithSizeLargerThan(&root, requiredCleanupSize) + if toDelete == nil { + return fmt.Errorf("cannot find directory to delete to free up %d", requiredCleanupSize) + } + fmt.Printf("delete %q, frees up %d\n", toDelete.name, toDelete.size) + return nil } From add03be9384f1d91191f31e2b52e0fad9af064b7 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 8 Dec 2022 09:15:03 +0100 Subject: [PATCH 030/120] Fix the command building logic golangs "closures" are weird. --- cmd/days.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/days.go b/cmd/days.go index 6e15cfa..9c4573a 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -33,11 +33,12 @@ var days = []day{ func init() { for index, day := range days { + run := day.run cmd := &cobra.Command{ Use: fmt.Sprintf("day%d", index + 1), Short: day.short, Run: func(cmd *cobra.Command, args []string) { - err := day.run(useSampleInput) + err := run(useSampleInput) if err != nil { fmt.Printf("Error: %v", err) os.Exit(1) From f8d9f328becfa32454eb058a8461657cf562dfb2 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 8 Dec 2022 09:16:42 +0100 Subject: [PATCH 031/120] Day 8, Task 1: 2D ... and the end of brute-force is near. --- .vscode/launch.json | 4 +- cmd/days.go | 2 + days/8/day8.go | 77 +++++++++++++++++++++++++++++++++++ days/8/input.txt | 99 +++++++++++++++++++++++++++++++++++++++++++++ days/8/sample.txt | 5 +++ 5 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 days/8/day8.go create mode 100644 days/8/input.txt create mode 100644 days/8/sample.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index b620041..aa7df26 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "mode": "debug", "request": "launch", "args": [ - "day7", + "day8", "--sample=true" ], "program": "${workspaceFolder}" @@ -21,7 +21,7 @@ "mode": "debug", "request": "launch", "args": [ - "day7", + "day8", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index 9c4573a..7427511 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -11,6 +11,7 @@ import ( day5 "github.com/ankon/adventofcode/2022/days/5" day6 "github.com/ankon/adventofcode/2022/days/6" day7 "github.com/ankon/adventofcode/2022/days/7" + day8 "github.com/ankon/adventofcode/2022/days/8" "github.com/spf13/cobra" ) @@ -29,6 +30,7 @@ var days = []day{ {"Supply Stacks", day5.Run}, {"Tuning Trouble", day6.Run}, {"No Space Left On Device", day7.Run}, + {"Treetop Tree House", day8.Run}, } func init() { diff --git a/days/8/day8.go b/days/8/day8.go new file mode 100644 index 0000000..a895c84 --- /dev/null +++ b/days/8/day8.go @@ -0,0 +1,77 @@ +package _8 + +import ( + _ "embed" + "fmt" + "strings" + + "github.com/ankon/adventofcode/2022/days" +) + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +type trees [][]byte + +type direction struct { + dx, dy int +} + +var directions = []direction{ + {0, -1}, + {1, 0}, + {0, 1}, + {-1, 0}, +} + +func isVisibleInDirection(trees trees, x, y int, d direction) bool { + height := len(trees) + width := len(trees[0]) + + t := trees[y][x] + x += d.dx + y += d.dy + for x >= 0 && x < width && y >= 0 && y < height { + if trees[y][x] >= t { + return false + } + x += d.dx + y += d.dy + } + return true +} + +func isVisible(trees trees, x, y int) bool { + for _, d := range directions { + if isVisibleInDirection(trees, x, y, d) { + return true + } + } + return false +} + +func Run(useSampleInput bool) error { + input := days.PickInput(useSampleInput, sampleInput, fullInput) + lines := strings.Split(strings.TrimSpace(input), "\n") + trees := make([][]byte, 0, len(lines)) + for _, line := range lines { + trees = append(trees, []byte(line)) + } + height := len(trees) + width := len(trees[0]) + + count := 0 + for y := 0; y < height; y++ { + for x := 0; x < width; x++ { + if isVisible(trees, x, y) { + count++ + } + } + } + fmt.Printf("%d visible trees\n", count) + + return nil +} diff --git a/days/8/input.txt b/days/8/input.txt new file mode 100644 index 0000000..ffdd5b1 --- /dev/null +++ b/days/8/input.txt @@ -0,0 +1,99 @@ +011201001000123232122300403211332202122424332111151523152310403222120311202224013311113203311122001 +102201211220103202323002411123324024134251423232343141424431144431022143443131141222323122010012220 +002022232232102013311311301321044421352134513235443522243113311323213013301030440423203311103101020 +002212021110130112400112141310424411421435324412235335534245212325313312413434430114302030310200000 +202000312203303110042324124431114212153432535412115323131323541522511253002131401212012131031321110 +120203002030304244102444143021314124552253521343321513511124144454343454102412220143321013220111212 +012133330030200444414333325255125142322121412245551424242135123513411533153323130432231002121211210 +012300220003100211444401144353345522135453435223464636451554321531323513234331131114224102232333310 +000201310302031301344341134512444312432566266533252332656654251123535525135213300040211242011230031 +121002133124022203240512452433331223524622643252532325346635555552514352434233454024134201432001111 +112213110140442401434531255323512525265655352543623565556265545555235551143135124203142220020302000 +033001202421424143555311243322416262636322654432542644633525453666655354514351121150231101002002310 +133303044321221102531154151541224245536464535622566355532543644552554644312231415325142303020031312 +112333344411024045335422225146442243536464622553556234523445362524655623435243115242532313102020021 +123023422310204444121415255225254435644446326664473564435422565325224635623542352154120001224144312 +102303024142131515433355242322223363453633455657436436574636544336652564626641215232314243234004001 +021344140434455245134415553542352643537665534644574553367446664254532523624521243554252411433032112 +100140101131444142414254644644434663647646555637737475474473636562243265243536422253531252202124322 +111043301134142345422324342454235374733474673456744577746755765343355535622342432251442244140231224 +232120141224122324244532255543256467566454337465647735433663734756446566663442525425254525142212311 +102310340244433433553362546534535757453376643763344566566557634664535744445254533545223521213213014 +330111232252114431226334564636467643777466445537346735563633337744734474466254662225321443542401243 +344311321253412213666443354643647347656735478884748547564466577774737677363226422622515344334010341 +222340105234132533423442424376674757757675647476557547564445666676437755355626455436313331225343402 +334241221121414455435265324646757456774784864846746867457546648735456677555624445353555434433340341 +333430021343121666326363537633737767788775478777445558858444854755434544735362564626265444342330020 +332224425333452333556456745375454657668644877658744844547774765844454475434765533256545152435214410 +411322431421116436336347456774356844455867864644844878664785864444475567664473365652253123453220003 +130345455115155526426437663665665668576686587847778476557678655576775553535745643522532344433523042 +241333521455132466523664543556384776587787745658797755565556576546847447434775733626365325451531301 +202135433134452323646546565545646885747548679876767658578565476458486465755545465664435422532454541 +344025243154435524235475655536845545775797795959686975588855546544875685664377465455353661444452422 +120511445324333353265334766654858656857755669695597899959957757545465687447345336332322634434414522 +041425252513666643357433333888555778459755889566967799659865567757457567576463765323236366123221323 +142343534134652443554434768544658774587669979986775985989879787975445856456554364645323653454511323 +443155144123223566654765746758688875856899955996667659755976778586644774777456744653322566354532232 +013242522162435447764573774877757879868788876799896979576555597985885468586473474464455426633333452 +101431333345553353553337548577478656967866886877887889699999856979976485874455544477534422463331314 +422325541533664573334736464857446675995799977868697688998787757585668584775766563477536636621514142 +313315332565562573637376866486547776557979868979996867779966955885566785455767644565336236452541411 +231122455364326235655644685888786685587796897688777698977986787596655865857448333576665523356143332 +314415154446535337443754887576795586569678967879977696896667866768856785586774365336636426455324541 +251324556334435537567468544665859588888869687767876697967887867856679658788866355353346553442543353 +134353225423362456734666455757877769577678987866887877799886886885859796767664444665534363236114533 +251241346545626367667578575687955957988796678987999979977897978877579787844755554533763646262143315 +353543555544353753474346565789555799696999667888997899777669899867697878476845756644734243432245123 +221521465632632737777766744748678869769669668898887888987898666789869785645678734643552655525624335 +351552456455622567337644647486678857766866879798779999878779869885869788874885873744772665326352324 +153242153665224557353455465857685566797887699998988788877767696668668675666664465757646436665554315 +321113152666424547657348876876678597898779877779998999978978777885976658558676664444674243656333212 +421511245364456777655754476646885699898678788797778788778778999795687589454774563737333365434325525 +213532265252653474345766566877669898969767779777879797899977669868595997784466766655547455234435452 +125232235356525353764645486577668857868788699799787978898988669878688867586564457353673236664223343 +441242562562223643773466848558599657669669968987979987787969676777796877655876456745562442232541525 +135122156635652746574578664849659556998698797778797889988788869797687977855447474475546334662522444 +144315413442434666777478887855885568968799966889978797797867786966685589646488554737453225335213325 +511213234443636433646678657654587788667696879878989799867699988765895758788675765445656425425334544 +052145146243336363474565857687976889776768867898889967686967668565998666768575534675445244546424155 +235513424332444756467574556745997958679678999799789777998968876679956958746554677637762355253554335 +331155256654246447545776676487485655676699678967897779688898989999768655488874564764434223445132152 +152152253254255234473347878744485766678897879689897888667968795675655864748584644653323363464154251 +245154344235223346354765457746867586969968687876867899766986679689585778787473555663424264553541344 +235253541263666477544377746867785766579566868896689699876766695956667455774677646576554255521144355 +033522343456423455634354575764856898657669957896677776766596688857787474488436433455326554242331222 +321532413246333226435563556578864759978657759897896799958558598588975755858856537673332523244522141 +101422552442534324467345475684574877989759655788785857697957976679848768474665346435664653421242444 +103425135453353666736674677847548667967885667765576995797857589796866646565443377775564436443333543 +041131245522253556554636537878457787468577768876778599999689667978487755747676763666266652435545351 +424232344536333364556466767555646468677996965895798968676966868665587584664535544755645232211324114 +334034423343366322247357747635787857555667756956768657779596877655676555367754633345545442422145333 +424344345121532564223643563774744574746844686888885779565686455664565643634566756543362551431252401 +232123114442152332546734767375678475664877645798695799654765488755876545334345452455463633534433233 +414423121145222454332477456654436757485685646546884446667744645744675377357654436554353221451345404 +234130223314353235262655676637577858558554556467788664555466588778677546456334642623666524333250443 +414001252524152463224524734765775677644765886656877578666575855788653533364773455446565352432424320 +024323134311552535243564667476365737764685474446876486685546667685363735646643655435355533243440034 +331141044111451522226436327536773637654887585478885586588745847444466365767232265352211455413531431 +241321311312323233252665352455436545735388846445565487667644555744667753556266645332452431541341044 +234030032312154414563442653244476576544654676884777445766434443476675746365245632242515342521301442 +202112004552434344564624422526757574735736566643654737673776743354737744242533546523434111443034202 +323422334452422412134566522262537334374446646774476534347655656336555632626663364214333341322443300 +031243421344143515452456444553266345437737337675574563437533573575456463665443432215213541123241240 +002114441013421154331235436253442576764555535635775735635377573353666526333623554524421352131443020 +111342301013125124521245222663363363467436357434736773473777464564655622533254352444544553311114233 +222323000331131531351433363334345533653474663466435557365553376535246564324662454422135233103003200 +002103300342403311123432563445263435443255635353333564444573456633466424623313351545133022013122320 +300304042333200223123432352234525626625234236453763536563235242224645265643515312312520000242200000 +210121244033001141551213125554433445222532265463624234562324443435344362451243522525243002401410013 +303323342040431313415255233251226626334264553655346266323665655652522363324341123235410333230402230 +300112203021311400115231251543524354554262365526643622264625434236554412121342322522123434120120203 +011001023222004142422445443143212526654365444643442536365453622222634154551441553400220414300301332 +230032020342121242113341435444543253355352433246243543645634456552525315313143243431133302112320020 +232132202131312144424224413332214322543242664652323324456222615212244414145113442320023403200012111 +112222030320432400004224215552515412325221525356363643351335211141344255554442403013303120331312202 +110321230332323212301432002424211134155124241552254334221154111545254253122214132321141212032221001 +021020121321302320401011302153145251455114411155452245422422135453412153112033343412340101230302010 +122203012232330222213342133012334131225335225325343355122151154444535354414423434423220001330003020 +221120213213221333210131242440001425551432522221141211124544343151315104244333311124033221102312011 +202201033331203122413021242022211002455531321354252412214332215513311231404032244320020330332301120 diff --git a/days/8/sample.txt b/days/8/sample.txt new file mode 100644 index 0000000..16d6fbd --- /dev/null +++ b/days/8/sample.txt @@ -0,0 +1,5 @@ +30373 +25512 +65332 +33549 +35390 From a977f021ae8e2b035fe39471b26296ed39fd9aeb Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 10 Dec 2022 14:03:40 +0100 Subject: [PATCH 032/120] Day 8, Task 2: Brute force still works ... --- days/8/day8.go | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/days/8/day8.go b/days/8/day8.go index a895c84..da72992 100644 --- a/days/8/day8.go +++ b/days/8/day8.go @@ -27,32 +27,53 @@ var directions = []direction{ {-1, 0}, } -func isVisibleInDirection(trees trees, x, y int, d direction) bool { +func visibilityInDirection(trees trees, x, y int, d direction) (int, bool) { height := len(trees) width := len(trees[0]) + result := 0 t := trees[y][x] x += d.dx y += d.dy for x >= 0 && x < width && y >= 0 && y < height { + result++ if trees[y][x] >= t { - return false + return result, false } x += d.dx y += d.dy } - return true + return result, true } -func isVisible(trees trees, x, y int) bool { +func isVisibleFromOutside(trees trees, x, y int) bool { for _, d := range directions { - if isVisibleInDirection(trees, x, y, d) { + if _, visibleFromOutside := visibilityInDirection(trees, x, y, d); visibleFromOutside { return true } } return false } +func calculateScenicScore(trees trees, x, y int) int { + result := 1 + for _, d := range directions { + distance, _ := visibilityInDirection(trees, x, y, d) + result *= distance + } + return result +} + +func printScenicScoreMap(scenicScoreMap [][]int) { + for y := 0; y < len(scenicScoreMap); y++ { + s := "" + for x := 0; x < len(scenicScoreMap[y]); x++ { + s += fmt.Sprintf("%4d ", scenicScoreMap[y][x]) + } + fmt.Println(s) + } +} + func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) lines := strings.Split(strings.TrimSpace(input), "\n") @@ -66,12 +87,27 @@ func Run(useSampleInput bool) error { count := 0 for y := 0; y < height; y++ { for x := 0; x < width; x++ { - if isVisible(trees, x, y) { + if isVisibleFromOutside(trees, x, y) { count++ } } } fmt.Printf("%d visible trees\n", count) + scenicScoreMap := make([][]int, height) + highestScenicScore := 0 + for y := 0; y < height; y++ { + scenicScoreMap[y] = make([]int, width) + for x := 0; x < width; x++ { + scenicScore := calculateScenicScore(trees, x, y) + scenicScoreMap[y][x] = scenicScore + if scenicScore > highestScenicScore { + highestScenicScore = scenicScore + } + } + } + fmt.Printf("highest scenic score %d\n", highestScenicScore) + printScenicScoreMap(scenicScoreMap) + return nil } From f62233511678b64c29fb2cb58ad87fd8e9a16b89 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 12:28:39 +0100 Subject: [PATCH 033/120] Day 9, Task 1: Don't enable visualization ... --- .vscode/launch.json | 4 +- cmd/days.go | 2 + days/9/day9.go | 180 ++++ days/9/input.txt | 2000 +++++++++++++++++++++++++++++++++++++++++++ days/9/sample.txt | 8 + 5 files changed, 2192 insertions(+), 2 deletions(-) create mode 100644 days/9/day9.go create mode 100644 days/9/input.txt create mode 100644 days/9/sample.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index aa7df26..5562ea7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "mode": "debug", "request": "launch", "args": [ - "day8", + "day9", "--sample=true" ], "program": "${workspaceFolder}" @@ -21,7 +21,7 @@ "mode": "debug", "request": "launch", "args": [ - "day8", + "day9", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index 7427511..245464a 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -12,6 +12,7 @@ import ( day6 "github.com/ankon/adventofcode/2022/days/6" day7 "github.com/ankon/adventofcode/2022/days/7" day8 "github.com/ankon/adventofcode/2022/days/8" + day9 "github.com/ankon/adventofcode/2022/days/9" "github.com/spf13/cobra" ) @@ -31,6 +32,7 @@ var days = []day{ {"Tuning Trouble", day6.Run}, {"No Space Left On Device", day7.Run}, {"Treetop Tree House", day8.Run}, + {"Rope Bridge", day9.Run}, } func init() { diff --git a/days/9/day9.go b/days/9/day9.go new file mode 100644 index 0000000..be9682e --- /dev/null +++ b/days/9/day9.go @@ -0,0 +1,180 @@ +package _9 + +import ( + _ "embed" + "fmt" + "strconv" + "strings" + + "github.com/ankon/adventofcode/2022/days" + "golang.org/x/exp/slices" +) + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +func Run(useSampleInput bool) error { + input := days.PickInput(useSampleInput, sampleInput, fullInput) + + steps := strings.Split(strings.TrimSpace(input), "\n") + _, trail, err := runSteps(steps) + if err != nil { + return nil + } + + fmt.Printf("Unique points in tail trail: %d\n", trail.uniquePoints()) + + return nil +} + +type point struct { + x, y int +} + +type trail struct { + symbol string + points []point + bottomLeft point + topRight point +} + +// Count the unique points in the trail +func (t *trail) uniquePoints() int { + var uniquePoints []point + for _, p := range t.points { + if !slices.Contains(uniquePoints, p) { + uniquePoints = append(uniquePoints, p) + } + } + + return len(uniquePoints) +} + +func (t *trail) current() point { + return t.points[len(t.points)-1] +} + +func (t *trail) add(p point) { + t.points = append(t.points, p) + if t.bottomLeft.x > p.x { + t.bottomLeft.x = p.x + } + if t.topRight.x < p.x { + t.topRight.x = p.x + } + if t.bottomLeft.y > p.y { + t.bottomLeft.y = p.y + } + if t.topRight.y < p.y { + t.topRight.y = p.y + } +} + +func (t *trail) show(otherPoints map[string]point) { + c := t.current() + for y := t.topRight.y; y >= t.bottomLeft.y; y-- { + line := fmt.Sprintf("%3d ", y) + nextX: + for x := t.bottomLeft.x; x <= t.topRight.x; x++ { + p := point{x, y} + for k, otherPoint := range otherPoints { + if p == otherPoint { + line += k + continue nextX + } + } + if p == c { + line += t.symbol + } else if slices.Contains(t.points, p) { + line += "#" + } else { + line += "." + } + + } + fmt.Println(line) + } +} + +func makeTrail(symbol string) trail { + return trail{ + symbol: symbol, + points: []point{{0, 0}}, + bottomLeft: point{0, 0}, + topRight: point{5, 5}, + } +} + +var directions = map[string]point{ + "R": {1, 0}, + "U": {0, 1}, + "L": {-1, 0}, + "D": {0, -1}, +} + +func runSteps(steps []string) (headtrail trail, tailtrail trail, err error) { + start := point{0, 0} + headtrail = makeTrail("H") + tailtrail = makeTrail("T") + for i, step := range steps { + d, c, found := strings.Cut(step, " ") + if !found { + return headtrail, tailtrail, fmt.Errorf("invalid step") + } + stepDelta, found := directions[d] + if !found { + return headtrail, tailtrail, fmt.Errorf("invalid direction %q", d) + } + count, err := strconv.Atoi(c) + if err != nil { + return headtrail, tailtrail, fmt.Errorf("invalid count %q", c) + } + + for i := 0; i < count; i++ { + // Move the head + newHead := point{ + headtrail.current().x + stepDelta.x, + headtrail.current().y + stepDelta.y, + } + headtrail.add(newHead) + + otherPoints := map[string]point{ + "s": start, + "H": newHead, + } + // fmt.Printf("\nBefore moving tail\n") + // tailtrail.show(otherPoints) + + // Check if the tail needs to move, if so, move it + tail := tailtrail.current() + touches := newHead.x >= tail.x-1 && newHead.x <= tail.x+1 && newHead.y >= tail.y-1 && newHead.y <= tail.y+1 + if !touches { + dy := newHead.y - tail.y + if dy < 0 { + dy = -1 + } else if dy > 0 { + dy = +1 + } + dx := newHead.x - tail.x + if dx < 0 { + dx = -1 + } else if dx > 0 { + dx = +1 + } + newTail := point{tail.x + dx, tail.y + dy} + tailtrail.add(newTail) + } + + if false { + fmt.Print("\033[H\033[2J") + tailtrail.show(otherPoints) + } + } + fmt.Printf("\rProcessed %d/%d steps", i, len(steps)) + } + + return headtrail, tailtrail, nil +} diff --git a/days/9/input.txt b/days/9/input.txt new file mode 100644 index 0000000..448850e --- /dev/null +++ b/days/9/input.txt @@ -0,0 +1,2000 @@ +D 2 +R 1 +U 1 +L 1 +D 2 +L 2 +R 1 +U 1 +D 2 +U 1 +R 1 +U 1 +D 2 +R 2 +L 2 +U 2 +D 1 +L 2 +R 2 +D 2 +U 2 +R 2 +U 1 +D 1 +L 2 +D 2 +L 2 +U 1 +R 2 +L 2 +D 2 +L 1 +D 2 +L 1 +R 2 +L 2 +U 1 +D 2 +L 1 +U 2 +R 1 +D 2 +L 2 +D 1 +L 2 +U 1 +L 1 +R 2 +U 2 +L 2 +D 1 +L 1 +D 1 +L 2 +R 1 +D 2 +U 2 +D 2 +R 1 +L 2 +R 2 +U 1 +R 1 +L 2 +U 2 +D 1 +U 2 +L 1 +R 2 +D 2 +L 2 +U 1 +L 1 +D 2 +R 2 +U 1 +R 2 +U 2 +D 2 +L 1 +U 1 +D 1 +R 1 +U 1 +D 2 +L 1 +D 2 +U 2 +D 1 +U 2 +L 2 +D 2 +R 2 +D 1 +R 2 +L 2 +U 1 +R 1 +L 1 +U 2 +D 2 +U 2 +L 2 +U 2 +R 2 +L 1 +U 1 +D 1 +L 2 +D 2 +R 2 +U 3 +R 3 +U 2 +L 1 +U 1 +L 1 +U 2 +R 2 +U 2 +D 1 +R 3 +D 1 +L 3 +R 2 +D 3 +U 1 +D 2 +L 2 +D 2 +L 1 +R 3 +D 1 +R 1 +L 3 +R 1 +U 2 +D 2 +L 3 +R 1 +U 2 +L 2 +R 3 +D 1 +U 2 +D 2 +L 3 +D 1 +R 3 +U 3 +R 2 +U 3 +D 1 +U 2 +R 2 +U 3 +R 1 +U 2 +L 3 +D 3 +U 1 +D 2 +U 2 +L 2 +R 1 +L 3 +R 1 +L 3 +U 2 +R 1 +U 1 +L 1 +R 2 +U 2 +D 1 +R 3 +D 3 +L 2 +D 2 +R 2 +L 3 +R 1 +L 1 +R 3 +L 3 +D 2 +U 1 +L 2 +U 3 +R 1 +L 1 +R 1 +L 1 +D 1 +R 2 +D 2 +U 1 +L 1 +D 3 +R 2 +D 1 +L 3 +R 3 +U 3 +D 2 +U 1 +D 2 +R 1 +U 1 +R 2 +D 2 +U 1 +D 3 +R 2 +U 3 +D 3 +R 1 +D 1 +U 2 +D 1 +U 2 +D 3 +U 3 +D 2 +R 4 +D 2 +R 1 +L 4 +U 2 +D 1 +U 2 +R 2 +U 1 +R 1 +U 4 +L 4 +U 3 +L 2 +U 3 +D 3 +R 2 +L 2 +U 3 +D 1 +L 3 +U 1 +L 1 +U 2 +L 4 +R 3 +U 3 +D 1 +L 3 +R 4 +D 4 +L 3 +R 4 +D 1 +R 4 +D 1 +L 3 +D 1 +L 1 +U 2 +D 1 +U 4 +R 1 +D 2 +U 2 +D 4 +U 3 +D 2 +L 4 +R 3 +U 3 +R 2 +D 3 +U 4 +R 4 +L 3 +U 2 +D 2 +U 2 +L 1 +R 3 +D 4 +U 1 +D 2 +U 1 +R 2 +L 2 +R 3 +U 4 +D 1 +L 1 +R 1 +D 4 +L 4 +D 4 +L 2 +R 3 +L 1 +U 2 +L 1 +D 3 +U 2 +R 2 +D 1 +R 1 +U 1 +L 2 +D 2 +U 3 +L 3 +U 1 +L 1 +D 1 +L 3 +R 4 +L 2 +R 1 +U 2 +D 4 +U 2 +L 4 +U 4 +R 1 +D 3 +U 2 +L 2 +D 4 +L 2 +U 1 +D 5 +L 5 +R 1 +D 1 +L 4 +D 5 +R 4 +U 2 +R 2 +L 2 +D 3 +U 4 +L 1 +U 1 +R 2 +L 4 +R 3 +U 1 +D 5 +U 4 +D 2 +R 3 +L 1 +D 4 +L 5 +D 1 +L 2 +U 1 +R 2 +L 2 +R 1 +L 2 +U 4 +D 1 +U 5 +L 2 +R 1 +D 5 +L 2 +D 5 +U 5 +R 3 +L 4 +D 2 +L 2 +D 2 +U 5 +R 3 +U 1 +D 3 +R 4 +U 3 +R 2 +U 3 +D 5 +U 4 +L 3 +R 3 +D 3 +R 1 +L 1 +D 4 +R 3 +D 2 +L 2 +R 4 +L 3 +R 2 +D 4 +L 3 +U 1 +D 2 +L 3 +U 4 +D 5 +U 2 +L 2 +R 1 +D 1 +L 3 +U 2 +R 4 +D 4 +L 4 +U 2 +D 1 +R 5 +L 3 +U 3 +L 5 +R 2 +D 1 +L 2 +D 2 +L 2 +R 4 +L 3 +D 3 +R 5 +L 5 +D 3 +R 5 +L 2 +R 1 +D 4 +L 2 +D 1 +U 2 +D 4 +U 5 +L 4 +D 2 +U 2 +D 4 +U 6 +L 3 +U 1 +D 2 +R 1 +U 5 +D 2 +L 4 +R 6 +U 2 +L 2 +D 1 +R 5 +U 2 +D 5 +R 5 +U 4 +D 6 +U 1 +D 2 +U 5 +D 5 +L 6 +U 5 +D 6 +L 4 +U 6 +R 5 +L 6 +D 5 +L 5 +D 6 +U 5 +L 6 +U 5 +L 3 +R 2 +D 1 +R 1 +L 6 +U 5 +D 1 +R 2 +D 2 +L 2 +D 6 +U 6 +L 1 +R 6 +L 3 +D 6 +R 3 +D 2 +U 5 +D 4 +L 2 +R 3 +D 5 +U 1 +D 3 +R 6 +U 4 +L 4 +U 4 +D 1 +R 4 +U 2 +R 6 +L 1 +D 3 +R 3 +U 1 +L 6 +R 4 +D 2 +U 2 +D 6 +L 4 +R 6 +U 3 +R 3 +D 3 +L 1 +R 5 +U 4 +R 6 +L 2 +R 1 +U 1 +L 6 +D 6 +L 3 +R 2 +D 6 +R 6 +L 3 +U 3 +D 1 +L 3 +D 1 +R 4 +D 3 +U 3 +D 2 +U 6 +D 4 +L 4 +R 5 +D 1 +L 7 +R 3 +L 5 +R 3 +U 6 +L 5 +U 3 +D 1 +L 5 +R 4 +L 1 +U 6 +L 1 +R 4 +D 3 +R 7 +D 7 +R 4 +L 4 +D 4 +L 2 +R 1 +U 7 +L 1 +D 7 +L 1 +D 1 +R 5 +D 5 +U 2 +L 6 +R 2 +U 5 +L 7 +D 7 +L 7 +U 1 +L 6 +D 2 +L 6 +U 2 +R 4 +U 7 +D 2 +L 6 +U 7 +R 5 +U 7 +L 7 +D 2 +R 4 +U 6 +R 1 +D 3 +R 2 +L 5 +R 5 +U 3 +L 5 +U 4 +D 4 +L 5 +R 1 +L 4 +D 5 +U 1 +L 4 +D 7 +R 6 +D 7 +U 7 +D 4 +R 1 +D 2 +L 5 +R 4 +D 3 +U 2 +D 4 +R 3 +L 4 +R 4 +U 3 +D 7 +R 2 +L 1 +D 5 +R 3 +D 2 +L 7 +R 3 +D 5 +R 1 +D 2 +R 6 +L 5 +R 7 +L 5 +U 2 +R 3 +D 6 +L 1 +D 4 +R 2 +U 1 +D 1 +R 6 +D 5 +L 3 +R 7 +L 3 +U 5 +R 5 +U 3 +D 8 +L 2 +U 6 +L 8 +U 4 +D 5 +R 7 +U 7 +L 4 +R 3 +L 3 +D 1 +L 6 +R 5 +L 6 +R 6 +L 8 +D 3 +U 2 +L 7 +R 2 +U 8 +D 3 +L 4 +R 3 +U 8 +R 3 +U 6 +D 8 +R 2 +L 8 +U 2 +R 5 +D 1 +U 1 +D 8 +R 4 +L 7 +D 2 +U 3 +D 1 +R 2 +U 1 +L 5 +U 4 +R 5 +D 6 +L 3 +U 1 +D 6 +U 6 +D 6 +U 2 +L 6 +U 6 +D 5 +L 1 +D 7 +U 2 +D 4 +L 5 +R 4 +D 2 +L 6 +U 2 +R 1 +U 4 +L 3 +D 3 +R 6 +D 4 +R 3 +L 2 +U 8 +R 5 +L 2 +U 3 +R 7 +U 7 +R 4 +U 5 +D 1 +L 8 +R 8 +U 3 +L 1 +U 7 +L 7 +D 2 +L 8 +D 7 +R 7 +L 3 +R 4 +L 3 +R 4 +U 6 +L 5 +R 4 +U 7 +L 3 +D 3 +R 2 +L 6 +U 3 +L 1 +R 8 +L 6 +D 7 +L 8 +R 7 +L 6 +D 2 +U 2 +R 3 +L 9 +R 7 +D 1 +R 9 +L 2 +D 5 +U 7 +D 5 +U 4 +L 4 +D 5 +L 6 +R 3 +U 2 +R 6 +D 3 +U 2 +R 1 +D 5 +U 6 +L 8 +D 8 +U 9 +L 2 +U 5 +L 2 +U 3 +L 4 +U 6 +L 3 +D 2 +R 5 +L 3 +R 8 +D 8 +U 8 +R 4 +U 2 +D 3 +L 9 +U 2 +L 4 +U 5 +R 5 +L 7 +U 9 +L 7 +U 5 +L 6 +U 6 +R 5 +L 9 +U 9 +R 3 +D 8 +U 8 +R 9 +D 4 +U 9 +D 9 +L 3 +R 2 +D 3 +U 1 +R 7 +D 5 +U 9 +D 7 +U 3 +D 8 +L 9 +U 1 +R 6 +L 8 +R 2 +L 7 +D 3 +U 4 +D 9 +L 1 +R 4 +D 9 +U 1 +D 1 +L 8 +U 2 +D 8 +U 1 +L 1 +U 2 +D 7 +L 1 +D 2 +L 6 +U 2 +D 8 +R 7 +L 4 +U 5 +R 2 +U 8 +D 6 +R 3 +D 8 +R 4 +L 5 +U 4 +L 1 +U 6 +L 10 +D 7 +R 5 +D 9 +U 6 +D 5 +L 9 +U 2 +R 3 +U 7 +R 7 +D 1 +R 4 +U 10 +D 4 +R 7 +L 7 +D 3 +R 5 +U 5 +D 6 +U 2 +D 2 +U 6 +D 5 +L 6 +U 10 +D 7 +R 6 +L 9 +R 7 +L 7 +U 6 +D 6 +R 8 +D 8 +R 4 +D 4 +L 1 +R 3 +U 5 +R 2 +L 9 +R 8 +L 3 +U 3 +R 6 +U 2 +L 6 +U 4 +D 5 +R 6 +U 5 +R 8 +U 10 +L 5 +U 2 +R 1 +D 9 +U 8 +D 2 +U 9 +L 7 +R 2 +D 10 +L 7 +D 3 +R 4 +L 2 +U 2 +R 7 +U 6 +D 9 +U 8 +L 7 +D 4 +U 4 +R 6 +U 3 +D 9 +L 1 +U 9 +R 9 +D 4 +L 9 +R 6 +L 6 +U 9 +L 10 +R 1 +L 5 +R 1 +L 2 +D 8 +U 2 +L 1 +R 4 +U 9 +L 3 +D 9 +L 6 +R 8 +U 6 +R 8 +L 5 +D 2 +R 5 +U 8 +R 2 +L 9 +R 3 +U 3 +R 8 +U 5 +D 5 +U 8 +D 10 +R 4 +L 5 +U 2 +L 4 +D 2 +L 1 +D 3 +U 8 +D 3 +U 4 +L 6 +D 6 +U 9 +L 5 +D 5 +U 10 +R 9 +D 2 +U 11 +D 4 +L 8 +D 8 +L 4 +U 6 +D 3 +R 9 +U 11 +L 7 +U 7 +D 9 +U 10 +D 9 +U 2 +R 2 +U 7 +R 2 +U 10 +R 7 +L 7 +U 6 +D 10 +L 5 +U 4 +D 4 +L 3 +D 3 +L 2 +R 5 +D 5 +U 10 +R 3 +U 8 +L 10 +U 5 +R 3 +L 9 +R 5 +D 1 +L 8 +R 8 +D 10 +L 6 +D 5 +L 6 +R 7 +D 10 +U 3 +D 9 +L 8 +D 5 +U 10 +L 5 +U 4 +D 7 +U 11 +L 6 +U 6 +L 9 +R 6 +U 8 +R 8 +L 6 +U 8 +L 8 +U 9 +D 4 +L 10 +D 6 +R 5 +D 8 +L 7 +D 6 +R 4 +D 11 +U 5 +D 4 +R 7 +U 11 +L 5 +U 7 +D 7 +L 11 +R 9 +U 1 +D 11 +R 8 +L 4 +R 2 +D 6 +L 4 +R 8 +D 9 +R 11 +U 2 +L 9 +U 6 +R 10 +L 11 +R 9 +D 10 +U 11 +L 6 +U 3 +L 2 +R 11 +L 2 +D 2 +L 5 +D 6 +U 11 +D 10 +U 8 +L 3 +R 9 +D 5 +R 9 +D 6 +R 2 +U 2 +D 11 +R 6 +U 9 +R 12 +U 6 +L 1 +D 2 +L 5 +D 9 +L 5 +D 4 +U 10 +L 12 +U 6 +R 6 +U 4 +L 4 +U 1 +L 4 +R 12 +L 11 +R 3 +U 10 +L 4 +R 11 +D 9 +L 9 +U 11 +D 1 +L 1 +R 3 +D 7 +U 6 +R 4 +D 3 +L 8 +U 5 +R 6 +L 9 +U 4 +L 6 +D 6 +U 6 +L 5 +R 7 +D 10 +R 5 +U 8 +L 5 +R 6 +U 10 +R 2 +U 2 +R 10 +U 12 +D 12 +L 7 +U 3 +R 1 +L 6 +D 6 +L 5 +D 8 +U 8 +D 11 +L 2 +D 10 +L 6 +R 10 +L 9 +D 5 +R 1 +D 7 +R 6 +U 10 +D 8 +R 9 +D 11 +R 8 +U 7 +R 10 +L 1 +U 3 +R 11 +D 11 +L 8 +D 13 +U 6 +D 12 +U 2 +L 2 +U 11 +D 1 +R 3 +U 8 +R 4 +L 3 +U 7 +D 4 +L 3 +R 2 +L 3 +R 6 +D 13 +L 1 +R 8 +L 5 +R 11 +D 7 +L 8 +D 12 +U 12 +D 3 +L 6 +U 1 +R 7 +U 2 +D 9 +L 3 +U 11 +R 2 +U 6 +D 11 +L 10 +D 4 +U 13 +D 1 +R 11 +L 3 +U 2 +D 7 +R 8 +D 10 +R 12 +D 4 +R 1 +U 5 +R 5 +U 2 +R 12 +D 3 +L 8 +D 11 +U 3 +R 1 +U 2 +R 3 +D 5 +U 8 +D 4 +R 6 +L 2 +R 4 +U 6 +D 12 +L 7 +U 2 +L 8 +U 8 +R 13 +U 10 +L 11 +R 1 +D 4 +R 1 +U 5 +L 9 +D 9 +U 11 +D 13 +U 9 +R 2 +D 9 +U 6 +R 1 +D 12 +R 3 +U 1 +R 13 +U 11 +L 6 +R 3 +D 11 +U 13 +R 2 +U 8 +L 11 +R 12 +D 7 +L 11 +U 10 +D 2 +L 9 +R 1 +L 9 +R 10 +D 5 +U 7 +R 6 +D 11 +U 11 +L 7 +R 6 +L 12 +D 12 +L 5 +R 3 +L 12 +R 4 +L 7 +D 4 +U 11 +R 2 +L 9 +R 11 +D 14 +L 7 +R 10 +U 1 +D 2 +L 7 +D 2 +U 12 +R 2 +D 6 +R 12 +L 7 +D 4 +U 13 +L 11 +D 13 +R 11 +D 5 +U 14 +R 1 +L 8 +U 10 +R 3 +D 3 +L 13 +R 6 +U 5 +D 4 +L 12 +D 2 +R 9 +D 1 +R 7 +D 10 +U 14 +L 12 +R 11 +U 6 +D 11 +L 8 +D 2 +U 4 +L 1 +R 14 +D 8 +U 11 +L 13 +U 1 +D 2 +R 14 +D 10 +R 4 +L 1 +R 10 +U 9 +D 8 +L 10 +R 10 +U 6 +D 14 +L 10 +U 13 +R 8 +L 3 +D 6 +L 13 +D 11 +U 14 +R 13 +U 12 +L 2 +D 6 +U 13 +L 13 +U 12 +D 1 +U 10 +L 5 +U 3 +R 4 +D 10 +L 14 +U 8 +R 7 +U 6 +R 13 +D 14 +L 5 +U 6 +L 1 +D 7 +R 2 +D 14 +U 13 +R 3 +U 5 +R 13 +L 2 +D 12 +U 1 +R 11 +L 7 +U 2 +D 11 +L 2 +R 7 +D 7 +L 1 +U 10 +L 12 +R 6 +L 7 +R 4 +D 3 +R 3 +U 15 +D 13 +U 6 +D 6 +U 3 +R 14 +U 10 +L 1 +R 8 +D 7 +R 13 +D 10 +R 9 +U 11 +D 11 +U 4 +D 11 +U 10 +D 3 +R 12 +U 5 +D 1 +L 4 +R 10 +D 11 +U 2 +D 9 +U 12 +D 9 +R 3 +D 6 +U 4 +L 14 +R 15 +U 4 +D 11 +R 13 +L 3 +U 12 +R 5 +U 11 +L 11 +D 6 +U 15 +R 5 +U 5 +R 1 +D 8 +U 4 +L 12 +D 2 +U 9 +L 15 +D 6 +R 12 +L 10 +D 14 +R 14 +D 8 +L 2 +D 11 +U 13 +L 1 +R 8 +D 8 +L 5 +D 14 +R 10 +U 13 +R 10 +L 4 +R 5 +L 6 +U 7 +R 7 +L 5 +D 3 +L 15 +U 10 +D 6 +L 1 +R 15 +D 11 +U 13 +R 12 +U 4 +D 8 +L 4 +D 11 +R 12 +L 5 +D 2 +U 8 +D 8 +L 10 +U 16 +L 15 +D 9 +U 10 +R 16 +L 7 +R 7 +U 9 +D 12 +L 16 +U 12 +R 13 +U 5 +R 5 +U 8 +D 8 +U 15 +L 4 +R 2 +L 2 +U 10 +D 2 +U 6 +L 15 +R 11 +D 2 +L 5 +R 16 +L 13 +R 14 +U 5 +R 2 +L 11 +U 9 +D 4 +L 14 +U 6 +D 6 +U 7 +D 2 +U 5 +D 6 +U 10 +D 5 +L 11 +R 13 +L 9 +U 5 +R 7 +D 13 +U 12 +L 6 +U 14 +R 15 +L 3 +U 4 +D 4 +U 8 +R 1 +U 12 +L 7 +U 2 +L 11 +R 10 +D 6 +R 9 +L 6 +R 2 +L 16 +U 8 +D 16 +R 8 +U 7 +D 7 +U 12 +D 13 +L 14 +R 3 +U 7 +L 14 +R 14 +U 4 +D 15 +R 13 +D 2 +R 9 +D 14 +U 15 +D 8 +L 8 +R 10 +U 4 +D 5 +L 16 +D 17 +R 14 +U 10 +D 15 +L 15 +R 13 +L 17 +U 12 +R 1 +D 8 +U 2 +R 11 +U 8 +D 9 +R 6 +U 10 +D 3 +L 7 +R 4 +L 15 +U 14 +L 9 +R 15 +U 9 +D 5 +U 4 +D 10 +R 13 +U 9 +D 5 +R 12 +D 6 +U 7 +D 8 +L 7 +U 13 +D 5 +R 4 +L 10 +D 16 +L 11 +R 16 +L 16 +U 15 +D 1 +R 3 +L 13 +D 7 +U 1 +R 15 +U 15 +D 2 +U 3 +L 7 +U 4 +D 14 +L 10 +D 8 +U 8 +D 6 +R 16 +U 6 +D 7 +L 13 +U 3 +L 9 +R 10 +D 5 +R 2 +D 16 +U 14 +R 11 +D 10 +R 13 +U 12 +L 4 +U 7 +L 2 +R 5 +D 13 +U 3 +R 3 +U 16 +L 5 +R 13 +L 16 +D 7 +L 4 +R 14 +U 8 +L 9 +U 2 +L 10 +D 9 +R 17 +U 14 +R 2 +D 7 +U 14 +R 3 +U 3 +L 14 +D 16 +U 6 +L 5 +U 2 +R 7 +L 4 +U 3 +D 12 +L 7 +D 15 +U 6 +L 1 +D 5 +U 11 +L 9 +D 15 +L 12 +R 18 +L 4 +D 9 +U 17 +R 1 +D 5 +L 13 +U 16 +R 17 +U 10 +D 5 +L 16 +D 2 +R 10 +L 1 +U 14 +L 16 +U 3 +D 2 +R 5 +U 3 +R 17 +D 17 +L 15 +U 11 +L 16 +R 4 +L 3 +R 7 +L 5 +R 8 +U 15 +R 9 +U 9 +R 18 +L 17 +R 9 +U 18 +L 11 +U 14 +R 7 +L 16 +R 15 +L 1 +U 9 +L 10 +U 9 +L 14 +U 5 +D 1 +R 16 +D 6 +R 1 +D 14 +R 11 +U 10 +D 17 +L 12 +D 5 +U 4 +L 12 +U 1 +L 7 +R 13 +D 2 +U 14 +D 3 +U 6 +R 1 +U 2 +R 11 +U 9 +D 14 +R 9 +U 14 +R 9 +D 14 +R 2 +D 9 +U 8 +D 10 +U 3 +R 8 +D 11 +R 5 +U 4 +D 1 +U 16 +L 17 +U 1 +R 14 +U 10 +R 5 +U 12 +D 4 +R 10 +D 10 +L 5 +R 2 +L 18 +D 3 +L 17 +D 10 +U 4 +L 15 +U 4 +L 9 +U 14 +R 9 +U 16 +L 1 +R 7 +U 10 +D 1 +U 13 +D 15 +R 6 +U 2 +L 17 +U 11 +L 14 +U 12 +R 11 +U 4 +D 11 +R 7 +D 13 +U 16 +L 5 +U 7 +R 4 +L 17 +D 2 +U 18 +R 8 +U 16 +L 15 +R 8 +L 19 +U 17 +D 2 +U 8 +D 9 +U 3 +L 12 +U 16 +L 3 +R 14 +D 16 +U 11 +D 2 +L 16 +U 4 +L 18 +R 15 +U 9 +L 18 +U 11 +R 18 +L 13 +D 8 +U 12 +D 14 +L 12 +U 2 +D 13 +L 12 +U 16 +R 17 +L 14 +U 10 +R 15 +U 19 +L 17 +R 8 +L 17 +R 8 +U 4 +R 8 +U 11 +L 17 +R 8 +D 13 +U 6 +D 7 +R 9 +L 2 +R 4 +D 16 +L 2 +D 10 +U 4 +L 10 +D 14 +U 5 +D 7 +U 4 +D 16 +U 14 +L 4 +U 14 +L 3 +D 16 +L 14 +U 11 +D 3 +L 10 +U 8 +D 6 +L 9 +D 17 +R 16 diff --git a/days/9/sample.txt b/days/9/sample.txt new file mode 100644 index 0000000..9874df2 --- /dev/null +++ b/days/9/sample.txt @@ -0,0 +1,8 @@ +R 4 +U 4 +L 3 +D 1 +R 4 +D 1 +L 5 +R 2 From 256fa4e9f7c5a50dee4a9f5588c241137b0255f9 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 12:33:43 +0100 Subject: [PATCH 034/120] Mark up the debug-related parts Seems task 2 will require some more visualizations, so let's do this properly. Ideally we will modify the framework to pass this along, possibly with an option or by having a more special debug-enabled command handler. --- days/9/day9.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/days/9/day9.go b/days/9/day9.go index be9682e..e91edff 100644 --- a/days/9/day9.go +++ b/days/9/day9.go @@ -16,6 +16,8 @@ var sampleInput string //go:embed input.txt var fullInput string +const debug = false + func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) @@ -145,8 +147,12 @@ func runSteps(steps []string) (headtrail trail, tailtrail trail, err error) { "s": start, "H": newHead, } - // fmt.Printf("\nBefore moving tail\n") - // tailtrail.show(otherPoints) + + if debug { + fmt.Print("\033[H\033[2J") + fmt.Printf("\nBefore moving tail\n") + tailtrail.show(otherPoints) + } // Check if the tail needs to move, if so, move it tail := tailtrail.current() @@ -168,12 +174,11 @@ func runSteps(steps []string) (headtrail trail, tailtrail trail, err error) { tailtrail.add(newTail) } - if false { - fmt.Print("\033[H\033[2J") + if debug { tailtrail.show(otherPoints) } } - fmt.Printf("\rProcessed %d/%d steps", i, len(steps)) + fmt.Printf("Processed %d/%d steps\n", i, len(steps)) } return headtrail, tailtrail, nil From 7744eb478e1b15748f8290b75f9b0798da7f29f1 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 13:00:45 +0100 Subject: [PATCH 035/120] Expose the ability to configure the cobra command per day Cobra has the `.Flags().XXXVar` functions, which work really well here: We can configure the command to work with variables in the day package. --- cmd/days.go | 24 +++++++++++++++--------- days/9/day9.go | 7 ++++++- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/cmd/days.go b/cmd/days.go index 245464a..314a941 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -18,21 +18,26 @@ import ( ) type dayRunFunc func(bool) error +type configureCommandFunc func(*cobra.Command) + +var Default configureCommandFunc = func(c *cobra.Command) {} + type day struct { short string run dayRunFunc + configureCommand configureCommandFunc } var days = []day{ - {"Calorie Counting", day1.Run}, - {"Rock Paper Scissors", day2.Run}, - {"Rucksack Reorganization", day3.Run}, - {"Camp Cleanup", day4.Run}, - {"Supply Stacks", day5.Run}, - {"Tuning Trouble", day6.Run}, - {"No Space Left On Device", day7.Run}, - {"Treetop Tree House", day8.Run}, - {"Rope Bridge", day9.Run}, + {"Calorie Counting", day1.Run, Default}, + {short: "Rock Paper Scissors", run: day2.Run, configureCommand: Default}, + {"Rucksack Reorganization", day3.Run, Default}, + {"Camp Cleanup", day4.Run, Default}, + {"Supply Stacks", day5.Run, Default}, + {"Tuning Trouble", day6.Run, Default}, + {"No Space Left On Device", day7.Run, Default}, + {"Treetop Tree House", day8.Run, Default}, + {"Rope Bridge", day9.Run, day9.ConfigureCommand}, } func init() { @@ -49,6 +54,7 @@ func init() { } }, } + day.configureCommand(cmd) rootCmd.AddCommand(cmd) } } diff --git a/days/9/day9.go b/days/9/day9.go index e91edff..6609d5d 100644 --- a/days/9/day9.go +++ b/days/9/day9.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/ankon/adventofcode/2022/days" + "github.com/spf13/cobra" "golang.org/x/exp/slices" ) @@ -16,7 +17,11 @@ var sampleInput string //go:embed input.txt var fullInput string -const debug = false +var debug = false + +func ConfigureCommand(cmd *cobra.Command) { + cmd.Flags().BoolVar(&debug, "debug", false, "Enable debug output") +} func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) From bd48ccd359a7d20ee2502f9d06526c04cdfc7464 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 13:04:54 +0100 Subject: [PATCH 036/120] Extract the function for a trail to follow another trail's head --- days/9/day9.go | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/days/9/day9.go b/days/9/day9.go index 6609d5d..f16d1ef 100644 --- a/days/9/day9.go +++ b/days/9/day9.go @@ -80,6 +80,29 @@ func (t *trail) add(p point) { } } +func (t *trail) follow(other trail) { + // Check if the tail needs to move, if so, move it + head := other.current() + tail := t.current() + touches := head.x >= tail.x-1 && head.x <= tail.x+1 && head.y >= tail.y-1 && head.y <= tail.y+1 + if !touches { + dy := head.y - tail.y + if dy < 0 { + dy = -1 + } else if dy > 0 { + dy = +1 + } + dx := head.x - tail.x + if dx < 0 { + dx = -1 + } else if dx > 0 { + dx = +1 + } + newTail := point{tail.x + dx, tail.y + dy} + t.add(newTail) + } +} + func (t *trail) show(otherPoints map[string]point) { c := t.current() for y := t.topRight.y; y >= t.bottomLeft.y; y-- { @@ -159,25 +182,7 @@ func runSteps(steps []string) (headtrail trail, tailtrail trail, err error) { tailtrail.show(otherPoints) } - // Check if the tail needs to move, if so, move it - tail := tailtrail.current() - touches := newHead.x >= tail.x-1 && newHead.x <= tail.x+1 && newHead.y >= tail.y-1 && newHead.y <= tail.y+1 - if !touches { - dy := newHead.y - tail.y - if dy < 0 { - dy = -1 - } else if dy > 0 { - dy = +1 - } - dx := newHead.x - tail.x - if dx < 0 { - dx = -1 - } else if dx > 0 { - dx = +1 - } - newTail := point{tail.x + dx, tail.y + dy} - tailtrail.add(newTail) - } + tailtrail.follow(headtrail) if debug { tailtrail.show(otherPoints) From 174ed4e7cb3c280031ce8f9813758c6f34dbbfd3 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 13:21:00 +0100 Subject: [PATCH 037/120] Extend to support an arbitrary number of trails --- days/9/day9.go | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/days/9/day9.go b/days/9/day9.go index f16d1ef..3e0bae1 100644 --- a/days/9/day9.go +++ b/days/9/day9.go @@ -27,12 +27,12 @@ func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) steps := strings.Split(strings.TrimSpace(input), "\n") - _, trail, err := runSteps(steps) + tail, err := runSteps(steps, 1) if err != nil { return nil } - fmt.Printf("Unique points in tail trail: %d\n", trail.uniquePoints()) + fmt.Printf("Unique points in tail trail: %d\n", tail.uniquePoints()) return nil } @@ -80,7 +80,7 @@ func (t *trail) add(p point) { } } -func (t *trail) follow(other trail) { +func (t *trail) follow(other *trail) { // Check if the tail needs to move, if so, move it head := other.current() tail := t.current() @@ -129,8 +129,8 @@ func (t *trail) show(otherPoints map[string]point) { } } -func makeTrail(symbol string) trail { - return trail{ +func makeTrail(symbol string) *trail { + return &trail{ symbol: symbol, points: []point{{0, 0}}, bottomLeft: point{0, 0}, @@ -145,51 +145,61 @@ var directions = map[string]point{ "D": {0, -1}, } -func runSteps(steps []string) (headtrail trail, tailtrail trail, err error) { +func runSteps(steps []string, knots int) (tail trail, err error) { start := point{0, 0} - headtrail = makeTrail("H") - tailtrail = makeTrail("T") + trails := make(map[int]*trail) + trails[0] = makeTrail("H") + i := 1 + for ; i < knots; i++ { + trails[i] = makeTrail(strconv.Itoa(i)) + } + trails[i] = makeTrail("T") for i, step := range steps { d, c, found := strings.Cut(step, " ") if !found { - return headtrail, tailtrail, fmt.Errorf("invalid step") + return trail{}, fmt.Errorf("invalid step") } stepDelta, found := directions[d] if !found { - return headtrail, tailtrail, fmt.Errorf("invalid direction %q", d) + return trail{}, fmt.Errorf("invalid direction %q", d) } count, err := strconv.Atoi(c) if err != nil { - return headtrail, tailtrail, fmt.Errorf("invalid count %q", c) + return trail{}, fmt.Errorf("invalid count %q", c) } for i := 0; i < count; i++ { // Move the head + head := trails[0].current() newHead := point{ - headtrail.current().x + stepDelta.x, - headtrail.current().y + stepDelta.y, + head.x + stepDelta.x, + head.y + stepDelta.y, } - headtrail.add(newHead) + trails[0].add(newHead) otherPoints := map[string]point{ "s": start, - "H": newHead, + } + for t := 0; t < knots; t++ { + otherPoints[trails[t].symbol] = trails[t].current() } if debug { fmt.Print("\033[H\033[2J") - fmt.Printf("\nBefore moving tail\n") - tailtrail.show(otherPoints) + fmt.Printf("\nBefore moving tails\n") + trails[knots].show(otherPoints) } - tailtrail.follow(headtrail) + for t := 1; t <= knots; t++ { + trails[t].follow(trails[t-1]) + } if debug { - tailtrail.show(otherPoints) + trails[knots].show(otherPoints) } } fmt.Printf("Processed %d/%d steps\n", i, len(steps)) } - return headtrail, tailtrail, nil + return *trails[knots], nil } From 3c8369374f4f20fac2cae7bfbfba15d4fe727f5e Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 14:03:58 +0100 Subject: [PATCH 038/120] Improve showing of the trails 1. Include all other points, even if it means expanding the bounding box 2. Use the same priorities as in the example for picking a symbol ("H", sorted tail numbers, "s"). --- days/9/day9.go | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/days/9/day9.go b/days/9/day9.go index 3e0bae1..f6b2ae0 100644 --- a/days/9/day9.go +++ b/days/9/day9.go @@ -3,6 +3,7 @@ package _9 import ( _ "embed" "fmt" + "math" "strconv" "strings" @@ -104,19 +105,46 @@ func (t *trail) follow(other *trail) { } func (t *trail) show(otherPoints map[string]point) { + bottomLeft := t.bottomLeft + topRight := t.topRight + for _, p := range otherPoints { + if bottomLeft.x > p.x { + bottomLeft.x = p.x + } + if topRight.x < p.x { + topRight.x = p.x + } + if bottomLeft.y > p.y { + bottomLeft.y = p.y + } + if topRight.y < p.y { + topRight.y = p.y + } + } + c := t.current() - for y := t.topRight.y; y >= t.bottomLeft.y; y-- { + for y := topRight.y; y >= bottomLeft.y; y-- { line := fmt.Sprintf("%3d ", y) - nextX: - for x := t.bottomLeft.x; x <= t.topRight.x; x++ { + for x := bottomLeft.x; x <= topRight.x; x++ { p := point{x, y} - for k, otherPoint := range otherPoints { + lowestK := math.MaxInt + symbol := "" + for s, otherPoint := range otherPoints { if p == otherPoint { - line += k - continue nextX + k, err := strconv.Atoi(s) + if err == nil { + if k < lowestK { + lowestK = k + symbol = s + } + } else if s == "H" || lowestK == math.MaxInt { + symbol = s + } } } - if p == c { + if symbol != "" { + line += symbol + } else if p == c { line += t.symbol } else if slices.Contains(t.points, p) { line += "#" From 3b2ee0cd5fbeb64d7798b9282cd24df8dc8d3d3f Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 14:05:10 +0100 Subject: [PATCH 039/120] Enable debugging for the sample launch --- .vscode/launch.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 5562ea7..1ccdbdf 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,8 @@ "request": "launch", "args": [ "day9", - "--sample=true" + "--sample=true", + "--debug" ], "program": "${workspaceFolder}" }, From c9efc48b8d8ef37296282d672ba63cd5cad9154b Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 14:06:14 +0100 Subject: [PATCH 040/120] Fix an off-by-one when setting up the rope While there: Improve the debug output to avoid confusing situations where the "H" is always one further than the tails. --- days/9/day9.go | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/days/9/day9.go b/days/9/day9.go index f6b2ae0..d28b392 100644 --- a/days/9/day9.go +++ b/days/9/day9.go @@ -174,14 +174,20 @@ var directions = map[string]point{ } func runSteps(steps []string, knots int) (tail trail, err error) { + if knots < 2 { + return trail{}, fmt.Errorf("need at least 2 knots") + } start := point{0, 0} trails := make(map[int]*trail) trails[0] = makeTrail("H") - i := 1 - for ; i < knots; i++ { - trails[i] = makeTrail(strconv.Itoa(i)) + if knots == 2 { + trails[1] = makeTrail("T") + } else { + i := 1 + for ; i < knots; i++ { + trails[i] = makeTrail(strconv.Itoa(i)) + } } - trails[i] = makeTrail("T") for i, step := range steps { d, c, found := strings.Cut(step, " ") if !found { @@ -204,30 +210,24 @@ func runSteps(steps []string, knots int) (tail trail, err error) { head.y + stepDelta.y, } trails[0].add(newHead) - - otherPoints := map[string]point{ - "s": start, - } - for t := 0; t < knots; t++ { - otherPoints[trails[t].symbol] = trails[t].current() - } - - if debug { - fmt.Print("\033[H\033[2J") - fmt.Printf("\nBefore moving tails\n") - trails[knots].show(otherPoints) - } - - for t := 1; t <= knots; t++ { + for t := 1; t < knots; t++ { trails[t].follow(trails[t-1]) } if debug { - trails[knots].show(otherPoints) + otherPoints := map[string]point{ + "s": start, + } + for t := 0; t < knots; t++ { + otherPoints[trails[t].symbol] = trails[t].current() + } + + fmt.Print("\033[H\033[2J") + trails[knots-1].show(otherPoints) } } fmt.Printf("Processed %d/%d steps\n", i, len(steps)) } - return *trails[knots], nil + return *trails[knots-1], nil } From d663783f19fc617070e30da91541bbb4216ccc31 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 14:07:06 +0100 Subject: [PATCH 041/120] Day 9, Task 2: More knots Now that everything else is implemented this simply runs the simulation with 10 knots again. Note that this does switch to the second sample input for the second simulation as well. --- days/9/day9.go | 14 ++++++++++++-- days/9/sample-2.txt | 8 ++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 days/9/sample-2.txt diff --git a/days/9/day9.go b/days/9/day9.go index d28b392..68a545d 100644 --- a/days/9/day9.go +++ b/days/9/day9.go @@ -15,6 +15,9 @@ import ( //go:embed sample.txt var sampleInput string +//go:embed sample-2.txt +var sampleInput2 string + //go:embed input.txt var fullInput string @@ -28,12 +31,19 @@ func Run(useSampleInput bool) error { input := days.PickInput(useSampleInput, sampleInput, fullInput) steps := strings.Split(strings.TrimSpace(input), "\n") - tail, err := runSteps(steps, 1) + tail, err := runSteps(steps, 2) if err != nil { return nil } + fmt.Printf("Unique points in tail trail (2 knots): %d\n", tail.uniquePoints()) - fmt.Printf("Unique points in tail trail: %d\n", tail.uniquePoints()) + input = days.PickInput(useSampleInput, sampleInput2, fullInput) + steps = strings.Split(strings.TrimSpace(input), "\n") + tail, err = runSteps(steps, 10) + if err != nil { + return nil + } + fmt.Printf("Unique points in tail trail (10 knots): %d\n", tail.uniquePoints()) return nil } diff --git a/days/9/sample-2.txt b/days/9/sample-2.txt new file mode 100644 index 0000000..60bd43b --- /dev/null +++ b/days/9/sample-2.txt @@ -0,0 +1,8 @@ +R 5 +U 8 +L 8 +D 3 +R 17 +D 10 +L 25 +U 20 From 23a22aa3fd462a573a0ecce7b82363b114777b92 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 14:31:25 +0100 Subject: [PATCH 042/120] Day 10, Task 1: Back to simulating something ... interesting? --- .vscode/launch.json | 4 +- cmd/days.go | 2 + days/10/day10.go | 85 ++++++++++++++++++++++++++ days/10/input.txt | 139 +++++++++++++++++++++++++++++++++++++++++ days/10/sample.txt | 146 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 374 insertions(+), 2 deletions(-) create mode 100644 days/10/day10.go create mode 100644 days/10/input.txt create mode 100644 days/10/sample.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index 1ccdbdf..cdd9c06 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "mode": "debug", "request": "launch", "args": [ - "day9", + "day10", "--sample=true", "--debug" ], @@ -22,7 +22,7 @@ "mode": "debug", "request": "launch", "args": [ - "day9", + "day10", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index 314a941..717e4f2 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -5,6 +5,7 @@ import ( "os" day1 "github.com/ankon/adventofcode/2022/days/1" + day10 "github.com/ankon/adventofcode/2022/days/10" day2 "github.com/ankon/adventofcode/2022/days/2" day3 "github.com/ankon/adventofcode/2022/days/3" day4 "github.com/ankon/adventofcode/2022/days/4" @@ -38,6 +39,7 @@ var days = []day{ {"No Space Left On Device", day7.Run, Default}, {"Treetop Tree House", day8.Run, Default}, {"Rope Bridge", day9.Run, day9.ConfigureCommand}, + {"Cathode-Ray Tube", day10.Run, day10.ConfigureCommand}, } func init() { diff --git a/days/10/day10.go b/days/10/day10.go new file mode 100644 index 0000000..d63d3dd --- /dev/null +++ b/days/10/day10.go @@ -0,0 +1,85 @@ +package _9 + +import ( + _ "embed" + "fmt" + "strconv" + "strings" + + "github.com/ankon/adventofcode/2022/days" + "github.com/spf13/cobra" +) + +var trivialInput = "noop\naddx 3\naddx -5\n" + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +var debug = false + +func ConfigureCommand(cmd *cobra.Command) { + cmd.Flags().BoolVar(&debug, "debug", false, "Enable debug output") +} + +func Run(useSampleInput bool) error { + input := days.PickInput(useSampleInput, sampleInput, fullInput) + instructions := strings.Split(strings.TrimSpace(input), "\n") + + sum := 0 + err := simulateProgram(instructions, state{1}, func(cycle int, state state) { + if debug { + fmt.Printf("%d: X=%d\n", cycle, state.x) + } + if cycle == 20 || cycle == 60 || cycle == 100 || cycle == 140 || cycle == 180 || cycle == 220 { + sum += cycle * state.x + } + }) + if err != nil { + return err + } + fmt.Printf("Signal strength sum %d\n", sum) + + return nil +} + +type state struct { + x int +} + +func simulateProgram(instructions []string, initialState state, sample func(cycle int, state state)) error { + cycle := 1 + state := initialState + + tick := func() { + sample(cycle, state) + cycle++ + } + + for _, ins := range instructions { + op, arg, _ := strings.Cut(ins, " ") + + switch op { + case "noop": + tick() + case "addx": + tick() + + tick() + v, err := strconv.Atoi(arg) + if err != nil { + return fmt.Errorf("invalid arg %q to addx at %d", arg, cycle) + } + state.x += v + default: + return fmt.Errorf("invalid op %q at %d", op, cycle) + } + } + + // One more tick, to sample the end state + tick() + + return nil +} diff --git a/days/10/input.txt b/days/10/input.txt new file mode 100644 index 0000000..57f49a0 --- /dev/null +++ b/days/10/input.txt @@ -0,0 +1,139 @@ +noop +noop +noop +addx 6 +addx -1 +noop +addx 5 +noop +noop +addx -12 +addx 19 +addx -1 +noop +addx 4 +addx -11 +addx 16 +noop +noop +addx 5 +addx 3 +addx -2 +addx 4 +noop +noop +noop +addx -37 +noop +addx 3 +addx 2 +addx 5 +addx 2 +addx 10 +addx -9 +noop +addx 1 +addx 4 +addx 2 +noop +addx 3 +addx 2 +addx 5 +addx 2 +addx 3 +addx -2 +addx 2 +addx 5 +addx -40 +addx 25 +addx -22 +addx 2 +addx 5 +addx 2 +addx 3 +addx -2 +noop +addx 23 +addx -18 +addx 2 +noop +noop +addx 7 +noop +noop +addx 5 +noop +noop +noop +addx 1 +addx 2 +addx 5 +addx -40 +addx 3 +addx 8 +addx -4 +addx 1 +addx 4 +noop +noop +noop +addx -8 +noop +addx 16 +addx 2 +addx 4 +addx 1 +noop +addx -17 +addx 18 +addx 2 +addx 5 +addx 2 +addx 1 +addx -11 +addx -27 +addx 17 +addx -10 +addx 3 +addx -2 +addx 2 +addx 7 +noop +addx -2 +noop +addx 3 +addx 2 +noop +addx 3 +addx 2 +noop +addx 3 +addx 2 +addx 5 +addx 2 +addx -5 +addx -2 +addx -30 +addx 14 +addx -7 +addx 22 +addx -21 +addx 2 +addx 6 +addx 2 +addx -1 +noop +addx 8 +addx -3 +noop +addx 5 +addx 1 +addx 4 +noop +addx 3 +addx -2 +addx 2 +addx -11 +noop +noop +noop diff --git a/days/10/sample.txt b/days/10/sample.txt new file mode 100644 index 0000000..37ee8ee --- /dev/null +++ b/days/10/sample.txt @@ -0,0 +1,146 @@ +addx 15 +addx -11 +addx 6 +addx -3 +addx 5 +addx -1 +addx -8 +addx 13 +addx 4 +noop +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx -35 +addx 1 +addx 24 +addx -19 +addx 1 +addx 16 +addx -11 +noop +noop +addx 21 +addx -15 +noop +noop +addx -3 +addx 9 +addx 1 +addx -3 +addx 8 +addx 1 +addx 5 +noop +noop +noop +noop +noop +addx -36 +noop +addx 1 +addx 7 +noop +noop +noop +addx 2 +addx 6 +noop +noop +noop +noop +noop +addx 1 +noop +noop +addx 7 +addx 1 +noop +addx -13 +addx 13 +addx 7 +noop +addx 1 +addx -33 +noop +noop +noop +addx 2 +noop +noop +noop +addx 8 +noop +addx -1 +addx 2 +addx 1 +noop +addx 17 +addx -9 +addx 1 +addx 1 +addx -3 +addx 11 +noop +noop +addx 1 +noop +addx 1 +noop +noop +addx -13 +addx -19 +addx 1 +addx 3 +addx 26 +addx -30 +addx 12 +addx -1 +addx 3 +addx 1 +noop +noop +noop +addx -9 +addx 18 +addx 1 +addx 2 +noop +noop +addx 9 +noop +noop +noop +addx -1 +addx 2 +addx -37 +addx 1 +addx 3 +noop +addx 15 +addx -21 +addx 22 +addx -6 +addx 1 +noop +addx 2 +addx 1 +noop +addx -10 +noop +noop +addx 20 +addx 1 +addx 2 +addx 2 +addx -6 +addx -11 +noop +noop +noop From 4fe9d5c8bb6a0c23984795b0f62414cc83fe3d47 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 14:41:46 +0100 Subject: [PATCH 043/120] Day 10, Task 2: CRT as a sampler I think I got lucky with the initial structure, so that the changes for task 2 were fairly minimal, and up to the usual "before"/"during"/"after" tuning this worked immediately. --- days/10/day10.go | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/days/10/day10.go b/days/10/day10.go index d63d3dd..066557b 100644 --- a/days/10/day10.go +++ b/days/10/day10.go @@ -29,19 +29,51 @@ func Run(useSampleInput bool) error { instructions := strings.Split(strings.TrimSpace(input), "\n") sum := 0 - err := simulateProgram(instructions, state{1}, func(cycle int, state state) { + sampleTask1 := func(cycle int, state state) { if debug { fmt.Printf("%d: X=%d\n", cycle, state.x) } if cycle == 20 || cycle == 60 || cycle == 100 || cycle == 140 || cycle == 180 || cycle == 220 { sum += cycle * state.x } - }) + } + err := simulateProgram(instructions, state{1}, sampleTask1) if err != nil { return err } fmt.Printf("Signal strength sum %d\n", sum) + lines := []string{} + line := "" + pos := 0 + crt := func(cycle int, state state) { + if debug { + fmt.Printf("%d: Sprite at %d, drawing pos %d\n", cycle, state.x, pos) + fmt.Printf("%d: %s\n", cycle, line) + } + + if state.x - 1 <= pos && state.x + 1 >= pos { + line += "#" + } else { + line += "." + } + pos++ + + if cycle % 40 == 0 { + lines = append(lines, line) + line = "" + pos = 0 + } + } + err = simulateProgram(instructions, state{1}, crt) + if err != nil { + return err + } + fmt.Printf("CRT %d\n", sum) + for _, line := range lines { + fmt.Println(line) + } + return nil } From 6ef127b2527d8bad962f07fad395f1afd1eef2dc Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 16:40:00 +0100 Subject: [PATCH 044/120] Format the `trivialInput` constant for readability as a multi-line string --- days/10/day10.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/days/10/day10.go b/days/10/day10.go index 066557b..71aa846 100644 --- a/days/10/day10.go +++ b/days/10/day10.go @@ -10,7 +10,10 @@ import ( "github.com/spf13/cobra" ) -var trivialInput = "noop\naddx 3\naddx -5\n" +var trivialInput = ` + noop + addx 3 + addx -5` //go:embed sample.txt var sampleInput string From e11ea42aff8f4729bfe83fb32d87f95011d1da4e Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 16:40:26 +0100 Subject: [PATCH 045/120] Apply `go fmt` --- days/10/day10.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/days/10/day10.go b/days/10/day10.go index 71aa846..f8fabbb 100644 --- a/days/10/day10.go +++ b/days/10/day10.go @@ -55,14 +55,14 @@ func Run(useSampleInput bool) error { fmt.Printf("%d: %s\n", cycle, line) } - if state.x - 1 <= pos && state.x + 1 >= pos { + if state.x-1 <= pos && state.x+1 >= pos { line += "#" } else { line += "." } pos++ - if cycle % 40 == 0 { + if cycle%40 == 0 { lines = append(lines, line) line = "" pos = 0 From 489869dbe5215ebbd4ec94179c369ebbfa7d4b85 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 18:05:03 +0100 Subject: [PATCH 046/120] Day 11, Task 1: Parsing gets more complex Things still work, but we're getting into a situation where this feels a little bit "non-go-y". Especially passing around function pointers might be a bit weird. --- .vscode/launch.json | 4 +- cmd/days.go | 2 + days/11/day11.go | 243 ++++++++++++++++++++++++++++++++++++++++++++ days/11/input.txt | 55 ++++++++++ days/11/sample.txt | 27 +++++ 5 files changed, 329 insertions(+), 2 deletions(-) create mode 100644 days/11/day11.go create mode 100644 days/11/input.txt create mode 100644 days/11/sample.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index cdd9c06..ffe1b2f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "mode": "debug", "request": "launch", "args": [ - "day10", + "day11", "--sample=true", "--debug" ], @@ -22,7 +22,7 @@ "mode": "debug", "request": "launch", "args": [ - "day10", + "day11", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index 717e4f2..a44260d 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -6,6 +6,7 @@ import ( day1 "github.com/ankon/adventofcode/2022/days/1" day10 "github.com/ankon/adventofcode/2022/days/10" + day11 "github.com/ankon/adventofcode/2022/days/11" day2 "github.com/ankon/adventofcode/2022/days/2" day3 "github.com/ankon/adventofcode/2022/days/3" day4 "github.com/ankon/adventofcode/2022/days/4" @@ -40,6 +41,7 @@ var days = []day{ {"Treetop Tree House", day8.Run, Default}, {"Rope Bridge", day9.Run, day9.ConfigureCommand}, {"Cathode-Ray Tube", day10.Run, day10.ConfigureCommand}, + {"Monkey in the Middle", day11.Run, day11.ConfigureCommand}, } func init() { diff --git a/days/11/day11.go b/days/11/day11.go new file mode 100644 index 0000000..abb2254 --- /dev/null +++ b/days/11/day11.go @@ -0,0 +1,243 @@ +package _9 + +import ( + _ "embed" + "fmt" + "strconv" + "strings" + + "github.com/ankon/adventofcode/2022/days" + "github.com/spf13/cobra" + "golang.org/x/exp/slices" +) + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +var debug = false + +func ConfigureCommand(cmd *cobra.Command) { + cmd.Flags().BoolVar(&debug, "debug", false, "Enable debug output") +} + +func Run(useSampleInput bool) error { + input := days.PickInput(useSampleInput, sampleInput, fullInput) + lines := strings.Split(strings.TrimSpace(input), "\n") + + monkeys, err := parseMonkeys(lines) + if err != nil { + return err + } + + activities := countItemInspections(monkeys, 20) + slices.Sort(activities) + mostActivities := activities[len(activities)-1] + secondMostActivities := activities[len(activities)-2] + + fmt.Printf("inspections: %d * %d = %d", mostActivities, secondMostActivities, mostActivities*secondMostActivities) + + return nil +} + +type opFunc func(int) int +type testFunc func(int) int + +type monkey struct { + // Items the monkey has (only tracking the worry level) + items []int + + op opFunc + test testFunc + + inspections int +} + +func (m *monkey) inspectItem() (int, bool) { + if len(m.items) == 0 { + return 0, false + } + result := m.items[0] + m.items = m.items[1:] + m.inspections++ + return result, true +} + +func (m *monkey) catchItem(level int) { + m.items = append(m.items, level) +} + +const startItemsPrefix = " Starting items: " +const opPrefix = " Operation: new = " +const testDivisibleByPrefix = " Test: divisible by " +const testIfTrueThrowPrefix = " If true: throw to monkey " +const testIfFalseThrowPrefix = " If false: throw to monkey " + +func parseMonkey(lines []string) (monkey, int, error) { + items := []int{} + var op opFunc + var test testFunc + + i := 0 + for ; i < len(lines); i++ { + line := lines[i] + if line == "" { + break + } else if strings.HasPrefix(line, startItemsPrefix) { + ss := strings.Split(line[len(startItemsPrefix):], ",") + for _, s := range ss { + v, err := strconv.Atoi(strings.TrimSpace(s)) + if err != nil { + return monkey{}, i, fmt.Errorf("cannot parse starting items %q", ss) + } + items = append(items, v) + } + } else if strings.HasPrefix(line, opPrefix) { + ss := strings.Split(line[len(opPrefix):], " ") + arg1, _ := strconv.Atoi(ss[0]) + arg2, _ := strconv.Atoi(ss[2]) + + op = func(level int) int { + var result int + if ss[0] == "old" { + result = level + } else { + result = arg1 + } + var other int + if ss[2] == "old" { + other = level + } else { + other = arg2 + } + + switch ss[1] { + case "+": + result += other + case "-": + result -= other + case "*": + result *= other + case "/": + result /= other + } + + return result + } + } else if strings.HasPrefix(line, testDivisibleByPrefix) { + divisor, err := strconv.Atoi(line[len(testDivisibleByPrefix):]) + if err != nil { + return monkey{}, i, fmt.Errorf("cannot parse test %q", line) + } + ifTrueLine := lines[i+1] + trueMonkey, err := strconv.Atoi(ifTrueLine[len(testIfTrueThrowPrefix):]) + if err != nil { + return monkey{}, i, fmt.Errorf("cannot parse expected true condition %q", ifTrueLine) + } + ifFalseLine := lines[i+2] + falseMonkey, err := strconv.Atoi(ifFalseLine[len(testIfFalseThrowPrefix):]) + if err != nil { + return monkey{}, i, fmt.Errorf("cannot parse expected false condition %q", ifFalseLine) + } + i += 2 + + test = func(level int) int { + if level%divisor == 0 { + return trueMonkey + } else { + return falseMonkey + } + } + } + } + + return monkey{items, op, test, 0}, i, nil +} + +func parseMonkeys(lines []string) ([]*monkey, error) { + result := []*monkey{} + for l := 0; l < len(lines); l++ { + line := lines[l] + if strings.TrimSpace(line) == "" { + continue + } + + id := 0 + n, err := fmt.Sscanf(line, "Monkey %d:", &id) + if err != nil { + return nil, fmt.Errorf("cannot parse monkey line at %d", l) + } + if n != 1 { + return nil, fmt.Errorf("expected monkey line at %d", l) + } + if id != len(result) { + return nil, fmt.Errorf("expected monkey id %d, but got %d at %d", len(result), id, l) + } + + m, consumed, err := parseMonkey(lines[l+1:]) + if err != nil { + return nil, err + } + result = append(result, &m) + + l += consumed + } + + return result, nil +} + +func playRound(monkeys []*monkey) { + for i, m := range monkeys { + if debug { + fmt.Printf("Monkey %d:\n", i) + } + for { + item, ok := m.inspectItem() + if !ok { + break + } + + if debug { + fmt.Printf(" Monkey inspects an item with a worry level of %d.\n", item) + } + + level := m.op(item) + if debug { + fmt.Printf(" Worry level is now %d.\n", level) + } + + level /= 3 + if debug { + fmt.Printf(" Monkey gets bored with item. Worry level is divided by 3 to %d.\n", level) + } + + throwTo := m.test(level) + if debug { + fmt.Printf(" Item with worry level %d is thrown to monkey %d.\n", level, throwTo) + } + + monkeys[throwTo].catchItem(level) + } + } +} + +func countItemInspections(monkeys []*monkey, rounds int) []int { + for round := 0; round < rounds; round++ { + playRound(monkeys) + + if debug { + fmt.Printf("After round %d, the monkeys are holding items with these worry levels:\n", round+1) + for k, m := range monkeys { + fmt.Printf("Monkey %d: %v\n", k, m.items) + } + } + } + + result := make([]int, len(monkeys)) + for i, m := range monkeys { + result[i] = m.inspections + } + return result +} diff --git a/days/11/input.txt b/days/11/input.txt new file mode 100644 index 0000000..ef22f88 --- /dev/null +++ b/days/11/input.txt @@ -0,0 +1,55 @@ +Monkey 0: + Starting items: 66, 79 + Operation: new = old * 11 + Test: divisible by 7 + If true: throw to monkey 6 + If false: throw to monkey 7 + +Monkey 1: + Starting items: 84, 94, 94, 81, 98, 75 + Operation: new = old * 17 + Test: divisible by 13 + If true: throw to monkey 5 + If false: throw to monkey 2 + +Monkey 2: + Starting items: 85, 79, 59, 64, 79, 95, 67 + Operation: new = old + 8 + Test: divisible by 5 + If true: throw to monkey 4 + If false: throw to monkey 5 + +Monkey 3: + Starting items: 70 + Operation: new = old + 3 + Test: divisible by 19 + If true: throw to monkey 6 + If false: throw to monkey 0 + +Monkey 4: + Starting items: 57, 69, 78, 78 + Operation: new = old + 4 + Test: divisible by 2 + If true: throw to monkey 0 + If false: throw to monkey 3 + +Monkey 5: + Starting items: 65, 92, 60, 74, 72 + Operation: new = old + 7 + Test: divisible by 11 + If true: throw to monkey 3 + If false: throw to monkey 4 + +Monkey 6: + Starting items: 77, 91, 91 + Operation: new = old * old + Test: divisible by 17 + If true: throw to monkey 1 + If false: throw to monkey 7 + +Monkey 7: + Starting items: 76, 58, 57, 55, 67, 77, 54, 99 + Operation: new = old + 6 + Test: divisible by 3 + If true: throw to monkey 2 + If false: throw to monkey 1 diff --git a/days/11/sample.txt b/days/11/sample.txt new file mode 100644 index 0000000..30e09e5 --- /dev/null +++ b/days/11/sample.txt @@ -0,0 +1,27 @@ +Monkey 0: + Starting items: 79, 98 + Operation: new = old * 19 + Test: divisible by 23 + If true: throw to monkey 2 + If false: throw to monkey 3 + +Monkey 1: + Starting items: 54, 65, 75, 74 + Operation: new = old + 6 + Test: divisible by 19 + If true: throw to monkey 2 + If false: throw to monkey 0 + +Monkey 2: + Starting items: 79, 60, 97 + Operation: new = old * old + Test: divisible by 13 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 3: + Starting items: 74 + Operation: new = old + 3 + Test: divisible by 17 + If true: throw to monkey 0 + If false: throw to monkey 1 From dd342becc1e509c63689a46d1456a54b58918397 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 21:41:49 +0100 Subject: [PATCH 047/120] Add some prime-related utilities These appeared in a dead-end approach to Day 11, Task 2, but might turn out to be useful for later. --- utils/prime.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 utils/prime.go diff --git a/utils/prime.go b/utils/prime.go new file mode 100644 index 0000000..971208a --- /dev/null +++ b/utils/prime.go @@ -0,0 +1,37 @@ +package utils + +import ( + "math" + "sort" +) + +var knownPrimes = []int{2,3,5,7,11,13,17,19,23} + +func nextPrimeAfter(n int) int { + i := sort.SearchInts(knownPrimes, n + 1) + if i < len(knownPrimes) { + return knownPrimes[i] + } + for x := knownPrimes[i - 1] + 2; ; x++ { + if IsPrime(x) { + if len(knownPrimes) < 1000 { + knownPrimes = append(knownPrimes, x) + } + return x + } + } +} + +func IsPrime(p int) bool { + if p == 2 || p == 3 { + return true + } + + max := int(math.Ceil(math.Sqrt(float64(p)))) + for d := 2; d <= max; d = nextPrimeAfter(d) { + if p%d == 0 { + return false + } + } + return true +} From 1180129c340048e8f3a51ac40ad2ae4adaefa5bc Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 22:14:56 +0100 Subject: [PATCH 048/120] Switch to modulo-arithmetic --- days/11/README.md | 11 ++++++ days/11/day11.go | 93 +++++++++++++++++++++++++++-------------------- utils/modulo.go | 34 +++++++++++++++++ 3 files changed, 98 insertions(+), 40 deletions(-) create mode 100644 days/11/README.md create mode 100644 utils/modulo.go diff --git a/days/11/README.md b/days/11/README.md new file mode 100644 index 0000000..99fc0df --- /dev/null +++ b/days/11/README.md @@ -0,0 +1,11 @@ +# Ideas + +## Use unique prime factors + +Doesn't work, because the additions break. See the [2022_11_2-prime-factors branch]. + +## Modulo Arithmetics + +Secretly this was already obvious, but I don't like these. Still, probably what could work and is worth a try is simply to store everything modulo the product of the divisors. + +TODO: Verify that this is "mathematically sane". It should work for the additions, but ... diff --git a/days/11/day11.go b/days/11/day11.go index abb2254..f8c90ff 100644 --- a/days/11/day11.go +++ b/days/11/day11.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/ankon/adventofcode/2022/days" + "github.com/ankon/adventofcode/2022/utils" "github.com/spf13/cobra" "golang.org/x/exp/slices" ) @@ -43,14 +44,16 @@ func Run(useSampleInput bool) error { } type opFunc func(int) int -type testFunc func(int) int type monkey struct { // Items the monkey has (only tracking the worry level) items []int - op opFunc - test testFunc + op opFunc + + divisor int + testTrueMonkey int + testFalseMonkey int inspections int } @@ -75,10 +78,14 @@ const testDivisibleByPrefix = " Test: divisible by " const testIfTrueThrowPrefix = " If true: throw to monkey " const testIfFalseThrowPrefix = " If false: throw to monkey " +var modulo = 1 + func parseMonkey(lines []string) (monkey, int, error) { items := []int{} var op opFunc - var test testFunc + var divisor int + var testTrueMonkey int + var testFalseMonkey int i := 0 for ; i < len(lines); i++ { @@ -96,64 +103,62 @@ func parseMonkey(lines []string) (monkey, int, error) { } } else if strings.HasPrefix(line, opPrefix) { ss := strings.Split(line[len(opPrefix):], " ") - arg1, _ := strconv.Atoi(ss[0]) arg2, _ := strconv.Atoi(ss[2]) - op = func(level int) int { - var result int - if ss[0] == "old" { - result = level - } else { - result = arg1 + switch ss[1] { + case "+": + if ss[0] != "old" { + return monkey{}, i, fmt.Errorf("first operand must be %q for +", "old") } - var other int if ss[2] == "old" { - other = level - } else { - other = arg2 + return monkey{}, i, fmt.Errorf("second operand must not be %q for +", ss[2]) } - - switch ss[1] { - case "+": - result += other - case "-": - result -= other - case "*": - result *= other - case "/": - result /= other + op = func(item int) int { + return (item + arg2) % modulo } - - return result + case "*": + if ss[0] != "old" { + return monkey{}, i, fmt.Errorf("first operand must be %q for *", "old") + } + if ss[2] != "old" && !utils.IsPrime(arg2) { + return monkey{}, i, fmt.Errorf("second operand must be %q or prime for *", "old") + } + op = func(item int) int { + if ss[2] == "old" { + return int(utils.MultiplyMod(uint64(item), uint64(item), uint64(modulo))) + } else { + return int(utils.MultiplyMod(uint64(item), uint64(arg2), uint64(modulo))) + } + } + default: + return monkey{}, i, fmt.Errorf("unsupported operator %q", ss[1]) } } else if strings.HasPrefix(line, testDivisibleByPrefix) { - divisor, err := strconv.Atoi(line[len(testDivisibleByPrefix):]) + v, err := strconv.Atoi(line[len(testDivisibleByPrefix):]) if err != nil { return monkey{}, i, fmt.Errorf("cannot parse test %q", line) } + divisor = v + ifTrueLine := lines[i+1] - trueMonkey, err := strconv.Atoi(ifTrueLine[len(testIfTrueThrowPrefix):]) + v, err = strconv.Atoi(ifTrueLine[len(testIfTrueThrowPrefix):]) if err != nil { return monkey{}, i, fmt.Errorf("cannot parse expected true condition %q", ifTrueLine) } + testTrueMonkey = v + ifFalseLine := lines[i+2] - falseMonkey, err := strconv.Atoi(ifFalseLine[len(testIfFalseThrowPrefix):]) + v, err = strconv.Atoi(ifFalseLine[len(testIfFalseThrowPrefix):]) if err != nil { return monkey{}, i, fmt.Errorf("cannot parse expected false condition %q", ifFalseLine) } - i += 2 + testFalseMonkey = v - test = func(level int) int { - if level%divisor == 0 { - return trueMonkey - } else { - return falseMonkey - } - } + i += 2 } } - return monkey{items, op, test, 0}, i, nil + return monkey{items, op, divisor, testTrueMonkey, testFalseMonkey, 0}, i, nil } func parseMonkeys(lines []string) ([]*monkey, error) { @@ -183,6 +188,9 @@ func parseMonkeys(lines []string) ([]*monkey, error) { result = append(result, &m) l += consumed + + // XXX: Can we do this nicer? + modulo *= m.divisor } return result, nil @@ -213,7 +221,12 @@ func playRound(monkeys []*monkey) { fmt.Printf(" Monkey gets bored with item. Worry level is divided by 3 to %d.\n", level) } - throwTo := m.test(level) + var throwTo int + if level%m.divisor == 0 { + throwTo = m.testTrueMonkey + } else { + throwTo = m.testFalseMonkey + } if debug { fmt.Printf(" Item with worry level %d is thrown to monkey %d.\n", level, throwTo) } diff --git a/utils/modulo.go b/utils/modulo.go new file mode 100644 index 0000000..af8f2e7 --- /dev/null +++ b/utils/modulo.go @@ -0,0 +1,34 @@ +package utils + +// MultiplyMod multiplies two numbers modulo m +// +// Taken from https://en.wikipedia.org/wiki/Modular_arithmetic#Example_implementations +func MultiplyMod(a, b, m uint64) uint64 { + if ((a | b) & (0xFFFFFFFF << 32)) == 0 { + return a * b % m + } + + d := uint64(0) + mp2 := m >> 1 + if a >= m { + a %= m + } + if b >= m { + b %= m + } + for i := 0; i < 64; i++ { + if d > mp2 { + d = (d << 1) - m + } else { + d <<= 1 + } + if a&0x8000000000000000 != 0 { + d += b + } + if d >= m { + d -= m + } + a <<= 1 + } + return d +} From 7983207ac2beff1ca96628f9fc810e9345d3bfdb Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 22:30:10 +0100 Subject: [PATCH 049/120] Day 11, Task 2: Add configuration options to run with the needed settings (rounds=10000, no relief) --- days/11/day11.go | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/days/11/day11.go b/days/11/day11.go index f8c90ff..79d871c 100644 --- a/days/11/day11.go +++ b/days/11/day11.go @@ -18,10 +18,14 @@ var sampleInput string //go:embed input.txt var fullInput string -var debug = false +var debug = 0 +var rounds = 20 +var relief = true func ConfigureCommand(cmd *cobra.Command) { - cmd.Flags().BoolVar(&debug, "debug", false, "Enable debug output") + cmd.Flags().IntVar(&debug, "debug", debug, "Enable debug output (higher numbers mean more output)") + cmd.Flags().IntVar(&rounds, "rounds", rounds, "Number of rounds (20 for task 1, 10000 for task 2)") + cmd.Flags().BoolVar(&relief, "relief", relief, "Feel relief after inspection (true for task 1, false for task 2)") } func Run(useSampleInput bool) error { @@ -33,12 +37,12 @@ func Run(useSampleInput bool) error { return err } - activities := countItemInspections(monkeys, 20) + activities := countItemInspections(monkeys, rounds) slices.Sort(activities) mostActivities := activities[len(activities)-1] secondMostActivities := activities[len(activities)-2] - fmt.Printf("inspections: %d * %d = %d", mostActivities, secondMostActivities, mostActivities*secondMostActivities) + fmt.Printf("inspections: %d * %d = %d\n", mostActivities, secondMostActivities, mostActivities*secondMostActivities) return nil } @@ -198,7 +202,7 @@ func parseMonkeys(lines []string) ([]*monkey, error) { func playRound(monkeys []*monkey) { for i, m := range monkeys { - if debug { + if debug > 2 { fmt.Printf("Monkey %d:\n", i) } for { @@ -207,18 +211,20 @@ func playRound(monkeys []*monkey) { break } - if debug { + if debug > 2 { fmt.Printf(" Monkey inspects an item with a worry level of %d.\n", item) } level := m.op(item) - if debug { + if debug > 2 { fmt.Printf(" Worry level is now %d.\n", level) } - level /= 3 - if debug { - fmt.Printf(" Monkey gets bored with item. Worry level is divided by 3 to %d.\n", level) + if relief { + level /= 3 + if debug > 2 { + fmt.Printf(" Monkey gets bored with item. Worry level is divided by 3 to %d.\n", level) + } } var throwTo int @@ -227,7 +233,7 @@ func playRound(monkeys []*monkey) { } else { throwTo = m.testFalseMonkey } - if debug { + if debug > 2 { fmt.Printf(" Item with worry level %d is thrown to monkey %d.\n", level, throwTo) } @@ -237,20 +243,26 @@ func playRound(monkeys []*monkey) { } func countItemInspections(monkeys []*monkey, rounds int) []int { - for round := 0; round < rounds; round++ { + for round := 1; round <= rounds; round++ { playRound(monkeys) - if debug { - fmt.Printf("After round %d, the monkeys are holding items with these worry levels:\n", round+1) + if debug > 1 { + fmt.Printf("After round %d, the monkeys are holding items with these worry levels:\n", round) for k, m := range monkeys { fmt.Printf("Monkey %d: %v\n", k, m.items) } } + if debug > 0 && (round == 1 || round == 20 || round%1000 == 0) { + fmt.Printf("== After round %d ==\n", round) + for k, m := range monkeys { + fmt.Printf("Monkey %d inspected items %d times.\n", k, m.inspections) + } + } } result := make([]int, len(monkeys)) - for i, m := range monkeys { - result[i] = m.inspections + for k, m := range monkeys { + result[k] = m.inspections } return result } From b7015cbc2936d5f4f9cd3f5dffb69a4e1a681816 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 11 Dec 2022 22:31:45 +0100 Subject: [PATCH 050/120] Move the `modulo` var around and document it I need to ponder if this can be made nicer, but package-global levels are a valid thing in golang and this works surprisingly well. --- days/11/day11.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/days/11/day11.go b/days/11/day11.go index 79d871c..687dc01 100644 --- a/days/11/day11.go +++ b/days/11/day11.go @@ -22,6 +22,9 @@ var debug = 0 var rounds = 20 var relief = true +// The modulo to use for arithmetics, calculated from the divisors of the monkey test functions +var modulo = 1 + func ConfigureCommand(cmd *cobra.Command) { cmd.Flags().IntVar(&debug, "debug", debug, "Enable debug output (higher numbers mean more output)") cmd.Flags().IntVar(&rounds, "rounds", rounds, "Number of rounds (20 for task 1, 10000 for task 2)") @@ -82,8 +85,6 @@ const testDivisibleByPrefix = " Test: divisible by " const testIfTrueThrowPrefix = " If true: throw to monkey " const testIfFalseThrowPrefix = " If false: throw to monkey " -var modulo = 1 - func parseMonkey(lines []string) (monkey, int, error) { items := []int{} var op opFunc From 96872532d537f0351cc5fe797a64d1bfd950e018 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 12 Dec 2022 20:47:36 +0100 Subject: [PATCH 051/120] Ignore the `main` binary as well This one appears the default name when using `go build main.go`. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index cfa5180..733df4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ +# Binaries 2022 +main From c6f26d13d909f4e3d683d3e04b7db7a983b1ce1a Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 12 Dec 2022 21:32:28 +0100 Subject: [PATCH 052/120] Fix the package declarations --- days/10/day10.go | 2 +- days/11/day11.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/days/10/day10.go b/days/10/day10.go index f8fabbb..1a7ed18 100644 --- a/days/10/day10.go +++ b/days/10/day10.go @@ -1,4 +1,4 @@ -package _9 +package _10 import ( _ "embed" diff --git a/days/11/day11.go b/days/11/day11.go index 687dc01..23db4b7 100644 --- a/days/11/day11.go +++ b/days/11/day11.go @@ -1,4 +1,4 @@ -package _9 +package _11 import ( _ "embed" From 231de59f4071868d60a461c49eb79d0ed7bed852 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 12 Dec 2022 21:32:47 +0100 Subject: [PATCH 053/120] Extract a generic stack implementation from Day 5 --- days/5/day5.go | 43 ++++++++++--------------------------------- utils/stack.go | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 33 deletions(-) create mode 100644 utils/stack.go diff --git a/days/5/day5.go b/days/5/day5.go index 2f5527c..e344f73 100644 --- a/days/5/day5.go +++ b/days/5/day5.go @@ -7,33 +7,10 @@ import ( "strings" "github.com/ankon/adventofcode/2022/days" + "github.com/ankon/adventofcode/2022/utils" ) -type stack struct { - // Crates are named by single (upper-case) letters. - crates []byte -} - -func (s *stack) Top() byte { - return s.crates[len(s.crates)-1] -} - -func (s *stack) Pop() byte { - end := len(s.crates)-1 - result := s.crates[end] - s.crates = s.crates[:end] - return result -} - -func (s *stack) Push(x byte) { - s.crates = append(s.crates, x) -} - -func (s *stack) Clone() stack { - result := stack{} - result.crates = append(result.crates, s.crates...) - return result -} +type crateStack = utils.Stack[byte] type action struct { from int @@ -53,7 +30,7 @@ var sampleInput string //go:embed input.txt var fullInput string -func simulateActionsCrateMover9000(stacks []stack, actions []action) error { +func simulateActionsCrateMover9000(stacks []crateStack, actions []action) error { for _, action := range actions { for i := 0; i < action.count; i++ { x := stacks[action.from - 1].Pop() @@ -63,13 +40,13 @@ func simulateActionsCrateMover9000(stacks []stack, actions []action) error { return nil } -func simulateActionsCrateMover9001(stacks []stack, actions []action) error { +func simulateActionsCrateMover9001(stacks []crateStack, actions []action) error { for _, action := range actions { if action.count == 1 { x := stacks[action.from - 1].Pop() stacks[action.to - 1].Push(x) } else { - helper := stack{} + helper := crateStack{} for i := 0; i < action.count; i++ { x := stacks[action.from - 1].Pop() helper.Push(x) @@ -96,9 +73,9 @@ func parseAction(l string) (action, error) { return action{from,to,count}, nil } -func parseStacks(stackLines []string) ([]stack, error) { +func parseStacks(stackLines []string) ([]crateStack, error) { stackNames := stackLines[len(stackLines) - 1] - stacks := make([]stack, int(math.Ceil(float64(len(stackNames)) / 4))) + stacks := make([]crateStack, int(math.Ceil(float64(len(stackNames)) / 4))) for i := len(stackLines) - 2; i >= 0; i-- { stackLine := stackLines[i] for s := 0; s < (len(stackLine) + 1) / 4; s++ { @@ -116,7 +93,7 @@ func parseStacks(stackLines []string) ([]stack, error) { return stacks, nil } -func parseInput(input string) (stacks []stack, actions []action, err error) { +func parseInput(input string) (stacks []crateStack, actions []action, err error) { s := parsing_stacks stackLines := []string{} @@ -152,7 +129,7 @@ func parseInput(input string) (stacks []stack, actions []action, err error) { return stacks, actions, nil } -func getTopCrates(stacks []stack) string { +func getTopCrates(stacks []crateStack) string { result := "" for _, stack := range stacks { result += string(stack.Top()) @@ -167,7 +144,7 @@ func Run(useSampleInput bool) error { return fmt.Errorf("cannot parse input: %w", err) } - stacks := make([]stack, len(inputStacks)) + stacks := make([]crateStack, len(inputStacks)) for i, stack := range inputStacks { stacks[i] = stack.Clone() } diff --git a/utils/stack.go b/utils/stack.go new file mode 100644 index 0000000..d2f1991 --- /dev/null +++ b/utils/stack.go @@ -0,0 +1,27 @@ +package utils + +type Stack[T any] struct { + data []T +} + +func (s *Stack[T]) Top() T { + return s.data[len(s.data)-1] +} + +func (s *Stack[T]) Pop() T { + end := len(s.data)-1 + result := s.data[end] + s.data = s.data[:end] + return result +} + +func (s *Stack[T]) Push(x T) { + s.data = append(s.data, x) +} + +func (s *Stack[T]) Clone() Stack[T] { + result := Stack[T]{ + data: append([]T{}, s.data...), + } + return result +} From 876801c2db390f132cf12399a4852bf166ee50a5 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 12 Dec 2022 22:58:04 +0100 Subject: [PATCH 054/120] Add a stack.Len helper method --- utils/stack.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/stack.go b/utils/stack.go index d2f1991..3e9e730 100644 --- a/utils/stack.go +++ b/utils/stack.go @@ -4,6 +4,10 @@ type Stack[T any] struct { data []T } +func (s *Stack[T]) Len() int { + return len(s.data) +} + func (s *Stack[T]) Top() T { return s.data[len(s.data)-1] } From 1bb8331da99fcd0c75fc992f043df584cdd57b77 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 12 Dec 2022 22:58:51 +0100 Subject: [PATCH 055/120] Day 12, Task 1: Not A*, but gets the star --- .vscode/launch.json | 6 +- cmd/days.go | 2 + days/12/day12.go | 207 ++++++++++++++++++++++++++++++++++++++++++++ days/12/input.txt | 41 +++++++++ days/12/sample.txt | 5 ++ 5 files changed, 258 insertions(+), 3 deletions(-) create mode 100644 days/12/day12.go create mode 100644 days/12/input.txt create mode 100644 days/12/sample.txt diff --git a/.vscode/launch.json b/.vscode/launch.json index ffe1b2f..7fc6f7a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,9 +10,9 @@ "mode": "debug", "request": "launch", "args": [ - "day11", + "day12", "--sample=true", - "--debug" + "--debug=1" ], "program": "${workspaceFolder}" }, @@ -22,7 +22,7 @@ "mode": "debug", "request": "launch", "args": [ - "day11", + "day12", "--sample=false" ], "program": "${workspaceFolder}" diff --git a/cmd/days.go b/cmd/days.go index a44260d..483c98d 100644 --- a/cmd/days.go +++ b/cmd/days.go @@ -7,6 +7,7 @@ import ( day1 "github.com/ankon/adventofcode/2022/days/1" day10 "github.com/ankon/adventofcode/2022/days/10" day11 "github.com/ankon/adventofcode/2022/days/11" + day12 "github.com/ankon/adventofcode/2022/days/12" day2 "github.com/ankon/adventofcode/2022/days/2" day3 "github.com/ankon/adventofcode/2022/days/3" day4 "github.com/ankon/adventofcode/2022/days/4" @@ -42,6 +43,7 @@ var days = []day{ {"Rope Bridge", day9.Run, day9.ConfigureCommand}, {"Cathode-Ray Tube", day10.Run, day10.ConfigureCommand}, {"Monkey in the Middle", day11.Run, day11.ConfigureCommand}, + {"Hill Climbing Algorithm", day12.Run, day12.ConfigureCommand}, } func init() { diff --git a/days/12/day12.go b/days/12/day12.go new file mode 100644 index 0000000..ebe0761 --- /dev/null +++ b/days/12/day12.go @@ -0,0 +1,207 @@ +package _12 + +import ( + _ "embed" + "fmt" + "sort" + "strings" + + "github.com/ankon/adventofcode/2022/days" + "github.com/spf13/cobra" + "golang.org/x/exp/slices" +) + +//go:embed sample.txt +var sampleInput string + +//go:embed input.txt +var fullInput string + +var debug = 0 + +func ConfigureCommand(cmd *cobra.Command) { + cmd.Flags().IntVar(&debug, "debug", debug, "Enable debug output (higher numbers mean more output)") +} + +func Run(useSampleInput bool) error { + input := days.PickInput(useSampleInput, sampleInput, fullInput) + m, start, end, err := parseHeightmap(strings.TrimSpace(input)) + if err != nil { + return err + } + + p := m.findPath(start, end) + fmt.Printf("Shortest path: %d steps\n", len(p)-1) + + return nil +} + +type point struct { + x, y int +} +type heightmap [][]byte + +type directionSymbol = byte + +const ( + up directionSymbol = byte('^') + right directionSymbol = byte('>') + down directionSymbol = byte('v') + left directionSymbol = byte('<') +) + +type step struct { + point + directionSymbol +} + +type path []step + +func (p *path) show(width, height int) []string { + result := []string{} + for y := 0; y < height; y++ { + line := "" + for x := 0; x < width; x++ { + s := slices.IndexFunc(*p, func(step step) bool { + return step.x == x && step.y == y + }) + if s != -1 { + line += string((*p)[s].directionSymbol) + } else { + line += "." + } + } + result = append(result, line) + } + result = append(result, fmt.Sprintf("%*d", width, len(*p))) + return result +} + +func showMultiplePaths(paths []path, width, height int) { + // XXX: +1 for the length at the end + lines := make([][]string, height+1) + for _, p := range paths { + l := p.show(width, height) + for i, tmp := range l { + lines[i] = append(lines[i], tmp) + } + } + + for _, line := range lines { + fmt.Printf("%s\n", strings.Join(line, " ")) + } +} + +var directions = map[directionSymbol]point{ + up: {0, -1}, + right: {1, 0}, + down: {0, 1}, + left: {-1, 0}, +} + +func (h *heightmap) height() int { + return len(*h) +} +func (h *heightmap) width() int { + return len((*h)[0]) +} + +func (h *heightmap) findPath(start, end point) path { + width := h.width() + height := h.height() + + visited := make([][]bool, height) + for y := 0; y < height; y++ { + visited[y] = make([]bool, width) + } + + // Open paths, sorted by their (current) length + open := []path{ + {step{start, startSymbol}}, + } + visited[start.y][start.x] = true + + for len(open) > 0 { + if debug > 0 { + max := len(open) + if max > 10 { + max = 10 + } + showMultiplePaths(open[:max], width, height) + } + + // Take the last (shortest) one, expand the options, and then insert + // them into the correct place + p := open[len(open)-1] + open = open[:len(open)-1] + + last := p[len(p)-1] + for s, d := range directions { + x := last.x + d.x + if x < 0 || x >= width { + continue + } + y := last.y + d.y + if y < 0 || y >= height { + continue + } + // XXX: We could go down, but should we? + if (*h)[y][x] > (*h)[last.y][last.x]+1 { + continue + } + n := point{x, y} + if !visited[n.y][n.x] { + visited[n.y][n.x] = true + newPath := append(path{}, p...) + newPath = append(newPath, step{n, s}) + newPathLen := len(newPath) + + if n == end { + // Found a result, and we know this is the shortest; if there are multiple + // then it will be at least as short. + return newPath + } + + // Find the point where we can insert the new path + i := sort.Search(len(open), func(i int) bool { + return newPathLen > len(open[i]) + }) + if i == len(open) { + // Put at the end + open = append(open, newPath) + } else { + // Insert _after_ the last element with the same length + for ; i < len(open) && len(open[i]) == newPathLen; i++ { + } + tmp := append([]path{}, open[:i]...) + tmp = append(tmp, newPath) + open = append(tmp, open[i:]...) + } + } + } + } + + return nil +} + +const startSymbol = byte('S') +const endSymbol = byte('E') + +func parseHeightmap(input string) (m heightmap, start point, end point, err error) { + m = [][]byte{} + for y, line := range strings.Split(input, "\n") { + data := []byte(line) + x := slices.Index(data, startSymbol) + if x != -1 { + start = point{x, y} + data[x] = byte('a') + } + x = slices.Index(data, endSymbol) + if x != -1 { + end = point{x, y} + data[x] = byte('z') + } + m = append(m, data) + } + return m, start, end, nil +} diff --git a/days/12/input.txt b/days/12/input.txt new file mode 100644 index 0000000..d469653 --- /dev/null +++ b/days/12/input.txt @@ -0,0 +1,41 @@ +abcccaaaaaaccccccccaaaaaccccccaaaaaaccccccaaaaaaaacccaaaaaaaccaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa +abcccaaaaaacccccccaaaaaaccccaaaaaaaacccccccaaaaaaaaaaaaaaaaccaaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa +abccccaaaaacaaaccaaaaaaaacccaaaaaaaaacccccccaaaaaaaaaaaaaaaacaaaaaacccccccccaaacccccccccccaaaaaaaaccccccccccaaccccccccccccccccaaaaaa +abccccaaaaccaaaaaaaaaaaaacccaaaaaaaaaacccccaaaaaaaaaaaaaaaaaaacaaaacccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccccccccccccccccccaaa +abcccccccccaaaaaacccaacccccccccaaacaaaccccccaacccccccaaaaaaaaacaacccccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccacaaccccccccccccaaa +abcccccccccaaaaaacccaacccccccccaaacccccccccccccccccccaaaacaaaacccccccaacaaccaaaccccccccccaccaaaaacacccccccccaaaacaaaaccccccccccccaac +abccccccccccaaaaacccccccccccccccacccaaaacccccccccccccaaaacccccccccccccaaaacccccccccccaacccccaaaaccccccccjjjjaaaaaaaaaccccccccccccccc +abccccccccccaaaacccccccccccccccccccaaaaacccccccccccccaaaccccccccccccccaaaaacccccccccaaaaaacccaaccccccccjjjjjjkkaaaacccccccccaacccccc +abcccccaaccccccccccccccccccccccccccaaaaaacccccccccccccaacccccccccccccaaaaaaccccccccccaaaaaccccccccccccjjjjjjjkkkkaacccccaacaaacccccc +abccaaaacccccccccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccaaaacaccccccccaaaaaaaccccaacccccjjjjoooookkkkkkkklllaaaaaaacccc +abccaaaaaacccccccccccccccccccccccccaaaaacccccccccccccccccccccccccccccccaaccccccccccaaaaaaaaccaaaaccccjjjoooooookkkkkkkllllaaaaaacccc +abcccaaaaacccccccccccccccccccccccccccaaaccccccccaaaacccccccccccccccccccccccccccccccaaaaaaaaccaaaaccccjjooooooooppkkppplllllaccaacccc +abccaaaaaccccccccccccaccccccccccccccccccccccccccaaaacccccccccccccccccccccccccccccccccaaacacccaaaacccijjooouuuuoppppppppplllccccccccc +abcccccaacccccccccccaaaaaaaaccccccccccccccccccccaaaaccccaaccccccccaaacccccccccccccaacaaccccccccccccciijoouuuuuuppppppppplllcccaccccc +abcccccccccccccccccccaaaaaaccccccccccccccccccccccaaccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiiiootuuuuuupuuuvvpppllccccccccc +abcccccccccccccccccccaaaaaaccaaaaacccccccccccccccccccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiinnotuuxxxuuuuvvvpppllccccccccc +abccccccccccccccacccaaaaaaaacaaaaaaacccccccccccccccccccaaaacccccccaaacccccaaaaccaaaaaccccaaccccccciiiinnnttxxxxuuyyyvvqqqllccccccccc +abcccccccccccaaaaccaaaaaaaaaaaaaaaaaaccaacccccccccccccccccccccccccccccccccaaaacccaaaaaccaaacccccciiinnnnnttxxxxxyyyyvvqqqllccccccccc +abaaaacccccccaaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccaaaacccaaaaaacaaaccccciiinnnnttttxxxxxyyyyvvqqmmmccccccccc +abaaaaccccccccaaaaacccaaaaacaaaaaacaaaaaaccccccccccccccccaaccccccccccccccccaacccccccaaaaaaaaaaciiinnnnttttxxxxxyyyyvvqqqmmmccccccccc +SbaaaacccccccaaaaaccccaaaaaccaaaaaaaaaaaccccccccccccccccaaacaacccccccccccccccccccccccaaaaaaaaachhhnnntttxxxEzzzzyyvvvqqqmmmccccccccc +abaaaacccccccaacaacccccaaaaaaaacaaaaaaaaaccccccccccccccccaaaaaccccccccccccccccccccccccaaaaaaacchhhnnntttxxxxxyyyyyyvvvqqmmmdddcccccc +abaaaacccccccccccccccccccaaaaaacaaaaaaaaaacccccccccccccaaaaaaccccccccaaaccccccccccccccaaaaaaccchhhnnntttxxxxywyyyyyyvvvqqmmmdddccccc +abaacccccccccccccccccccaaaaaaacccccaaaaaaacccccccccccccaaaaaaaacccccaaaacccccccccccccaaaaaaacaahhhmmmttttxxwwyyyyyyyvvvqqmmmdddccccc +abcccccccccccccccccccccaaaaaaacaaccaaacccccccccccccccccaacaaaaacccccaaaacccccccccccccaaacaaaaaahhhmmmmtsssswwyywwwwvvvvqqqmmdddccccc +abcccccccccccccccaaaccccaaaaaaaaaacaaccaaccccccccccccccccaaacaccccccaaaacccccccccccccccccaaaaacahhhmmmmmsssswwywwwwwvvrrqqmmdddccccc +abcccccccccccccaaaaaaccccaaaaaaaaaccaaaacccccccccccccccccaacccccccccccccccccccccccaaaccccaaaaaaahhhhhmmmmssswwwwwrrrrrrrrmmmmddccccc +abcccccccccccccaaaaaaccccaaaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaacccccaaaaachhhhhmmmmsswwwwrrrrrrrrrkkmdddccccc +abccccccccccccccaaaaaccccccaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaaccccaaaaacccchhggmmmssswwrrrrrkkkkkkkkdddacccc +abccaaaacccccccaaaaacccccccccaaaaaacaaaaacccccccccccccccccccccccccccccccccccccccaaaaaaccccaacaaaccccggggmmsssssrrlkkkkkkkkkdddaccccc +abccaaaacccccccaaaaacccccccccaaaaaaccccaacccccccccccccccccccccccccccccccccccccccaaaaaccccccccaaccccccgggmllssssrllkkkkkkkeeeddaccccc +abccaaaacccccccaaacccccccccccaaaaaacccccccccccccccccccaacccccccccccccccccccccccaaaaaacccccccccccccccccggllllssslllkkeeeeeeeeeaaacccc +abcccaaccccccccaaacaaaccccccaaaaaaaaaaacccccccccccccaaaaaacccccccccccccccccccccaaacaaacccccaacccccccccggglllllllllfeeeeeeeeaaaaacccc +abccccccccccaaaaaaaaaaccccccccccccaccaaaccacccccccccaaaaaaccccaaccaacccaaccccccaaaaaaacccccaaccccccccccggglllllllfffeeecccaaaaaacccc +abccccccccccaaaaaaaaacccccccccccccccaaaaaaaccccccccccaaaaaccccaaaaaacccaaaaaaccaaaaaacccaaaaaaaacccccccggggllllfffffccccccaacccccccc +abcccccccccccaaaaaaacccccccccccccccccaaaaaaccaacccccaaaaaccccccaaaaacccaaaaaacaaaaaaacccaaaaaaaaccccccccgggffffffffccccccccccccccccc +abccccccccccccaaaaaaacccccccccccccaaaaaaaaacaaaaccccaaaaacaaaaaaaaaacaaaaaaacaaaaaaaaaccccaaaacccccccccccggffffffacccccccccccccccaaa +abccccccccccccaaaaaaacaaccccccccccaaaaaaaaacaaaacccccaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaacccaaaaacccccccccccaffffaaaaccccccccccccccaaa +abccccccccccccaaacaaaaaacccccccccccaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaacccaaacaaaccaaaaaacccccccccccccccccaaaccccccccccccccaaa +abccccccccccccaaccaaaaaccccccccccccccaaaaaaaccccaaaaaaaaaaaaccccaacccccaaaaaacccaaaccccccaaccaacccccccccccccccccaaacccccccccccaaaaaa +abcccccccccccccccaaaaaaaaccccccccccccaacccacccccccaaaaaaaaaaccccaacccccaaccccccccaccccccccccccccccccccccccccccccccccccccccccccaaaaaa diff --git a/days/12/sample.txt b/days/12/sample.txt new file mode 100644 index 0000000..86e9cac --- /dev/null +++ b/days/12/sample.txt @@ -0,0 +1,5 @@ +Sabqponm +abcryxxl +accszExk +acctuvwj +abdefghi From 551d974773d5dbb2860215f98e7587b9c5767151 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 12 Dec 2022 23:07:24 +0100 Subject: [PATCH 056/120] Day 12, Task 2: If task 1 takes ages to calculate, don't try task 2 Find the shortest possible one from all the paths starting with 'a'. I guess one could do that smarter, for instance by searching from 'z' to any 'a', but given that the algorithm seems to be pretty fast we can just run it for all possible starting points. --- days/12/day12.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/days/12/day12.go b/days/12/day12.go index ebe0761..6ada2da 100644 --- a/days/12/day12.go +++ b/days/12/day12.go @@ -3,6 +3,7 @@ package _12 import ( _ "embed" "fmt" + "math" "sort" "strings" @@ -33,6 +34,20 @@ func Run(useSampleInput bool) error { p := m.findPath(start, end) fmt.Printf("Shortest path: %d steps\n", len(p)-1) + // Find all possible starting points (elevation = 'a') + shortestPathLen := math.MaxInt + for y := 0; y < m.height(); y++ { + for x := 0; x < m.width(); x++ { + if m[y][x] == byte('a') { + p := m.findPath(point{x, y}, end) + if p != nil && len(p) < shortestPathLen { + shortestPathLen = len(p) - 1 + } + } + } + } + fmt.Printf("Shortest possible path: %d steps\n", shortestPathLen) + return nil } From 415629387f7afb5419529fdb923dba2f2b246080 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 2 Dec 2023 12:02:55 +0100 Subject: [PATCH 057/120] Remove go and suggest the rust extension instead --- .gitignore | 2 - .vscode/extensions.json | 2 +- .vscode/launch.json | 23 - .vscode/settings.json | 3 - README.md | 5 +- cmd/days.go | 66 -- cmd/root.go | 28 - days/1/day1.go | 101 -- days/1/input.txt | 2246 ----------------------------------- days/1/sample.txt | 14 - days/10/day10.go | 120 -- days/10/input.txt | 139 --- days/10/sample.txt | 146 --- days/11/README.md | 11 - days/11/day11.go | 269 ----- days/11/input.txt | 55 - days/11/sample.txt | 27 - days/12/day12.go | 222 ---- days/12/input.txt | 41 - days/12/sample.txt | 5 - days/2/day2.go | 87 -- days/2/input.txt | 2500 --------------------------------------- days/2/sample.txt | 3 - days/3/day3.go | 96 -- days/3/input.txt | 300 ----- days/3/sample.txt | 6 - days/4/day4.go | 93 -- days/4/input.txt | 1000 ---------------- days/4/sample.txt | 6 - days/5/day5.go | 167 --- days/5/input.txt | 514 -------- days/5/sample.txt | 9 - days/6/day6.go | 84 -- days/6/input.txt | 1 - days/7/day7.go | 225 ---- days/7/input.txt | 1046 ---------------- days/7/sample.txt | 23 - days/8/day8.go | 113 -- days/8/input.txt | 99 -- days/8/sample.txt | 5 - days/9/day9.go | 243 ---- days/9/input.txt | 2000 ------------------------------- days/9/sample-2.txt | 8 - days/9/sample.txt | 8 - days/util.go | 9 - go.mod | 11 - go.sum | 13 - main.go | 7 - utils/modulo.go | 34 - utils/prime.go | 37 - utils/stack.go | 31 - 51 files changed, 3 insertions(+), 12300 deletions(-) delete mode 100644 cmd/days.go delete mode 100644 cmd/root.go delete mode 100644 days/1/day1.go delete mode 100644 days/1/input.txt delete mode 100644 days/1/sample.txt delete mode 100644 days/10/day10.go delete mode 100644 days/10/input.txt delete mode 100644 days/10/sample.txt delete mode 100644 days/11/README.md delete mode 100644 days/11/day11.go delete mode 100644 days/11/input.txt delete mode 100644 days/11/sample.txt delete mode 100644 days/12/day12.go delete mode 100644 days/12/input.txt delete mode 100644 days/12/sample.txt delete mode 100644 days/2/day2.go delete mode 100644 days/2/input.txt delete mode 100644 days/2/sample.txt delete mode 100644 days/3/day3.go delete mode 100644 days/3/input.txt delete mode 100644 days/3/sample.txt delete mode 100644 days/4/day4.go delete mode 100644 days/4/input.txt delete mode 100644 days/4/sample.txt delete mode 100644 days/5/day5.go delete mode 100644 days/5/input.txt delete mode 100644 days/5/sample.txt delete mode 100644 days/6/day6.go delete mode 100644 days/6/input.txt delete mode 100644 days/7/day7.go delete mode 100644 days/7/input.txt delete mode 100644 days/7/sample.txt delete mode 100644 days/8/day8.go delete mode 100644 days/8/input.txt delete mode 100644 days/8/sample.txt delete mode 100644 days/9/day9.go delete mode 100644 days/9/input.txt delete mode 100644 days/9/sample-2.txt delete mode 100644 days/9/sample.txt delete mode 100644 days/util.go delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100644 main.go delete mode 100644 utils/modulo.go delete mode 100644 utils/prime.go delete mode 100644 utils/stack.go diff --git a/.gitignore b/.gitignore index 733df4b..0100b4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ # Binaries -2022 -main diff --git a/.vscode/extensions.json b/.vscode/extensions.json index db58406..3d97f9e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,5 @@ { "recommendations": [ - "golang.Go" + "rust-lang.rust-analyzer", ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 7fc6f7a..8a7ebe2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,28 +4,5 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { - "name": "Sample", - "type": "go", - "mode": "debug", - "request": "launch", - "args": [ - "day12", - "--sample=true", - "--debug=1" - ], - "program": "${workspaceFolder}" - }, - { - "name": "Full", - "type": "go", - "mode": "debug", - "request": "launch", - "args": [ - "day12", - "--sample=false" - ], - "program": "${workspaceFolder}" - } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 04d1aba..33de8df 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,4 @@ { "editor.formatOnSave": true, "editor.formatOnSaveMode": "modificationsIfAvailable", - "[go]": { - "editor.defaultFormatter": "golang.go" - }, } diff --git a/README.md b/README.md index 3c10262..b37c775 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ My attempts at [saving the holidays](https://adventofcode.com/). -## Random Thoughts and Ideas +## 2023 Update -### Load the current task, and it's input, and auto-generate the command +This year, let's see how Rust fares. -We can use the title of the day as `Short`, and the full description as `Long` to capture everything. Will need the magic of github authentication though so it grabs the correct inputs... diff --git a/cmd/days.go b/cmd/days.go deleted file mode 100644 index 483c98d..0000000 --- a/cmd/days.go +++ /dev/null @@ -1,66 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - - day1 "github.com/ankon/adventofcode/2022/days/1" - day10 "github.com/ankon/adventofcode/2022/days/10" - day11 "github.com/ankon/adventofcode/2022/days/11" - day12 "github.com/ankon/adventofcode/2022/days/12" - day2 "github.com/ankon/adventofcode/2022/days/2" - day3 "github.com/ankon/adventofcode/2022/days/3" - day4 "github.com/ankon/adventofcode/2022/days/4" - day5 "github.com/ankon/adventofcode/2022/days/5" - day6 "github.com/ankon/adventofcode/2022/days/6" - day7 "github.com/ankon/adventofcode/2022/days/7" - day8 "github.com/ankon/adventofcode/2022/days/8" - day9 "github.com/ankon/adventofcode/2022/days/9" - - "github.com/spf13/cobra" -) - -type dayRunFunc func(bool) error -type configureCommandFunc func(*cobra.Command) - -var Default configureCommandFunc = func(c *cobra.Command) {} - -type day struct { - short string - run dayRunFunc - configureCommand configureCommandFunc -} - -var days = []day{ - {"Calorie Counting", day1.Run, Default}, - {short: "Rock Paper Scissors", run: day2.Run, configureCommand: Default}, - {"Rucksack Reorganization", day3.Run, Default}, - {"Camp Cleanup", day4.Run, Default}, - {"Supply Stacks", day5.Run, Default}, - {"Tuning Trouble", day6.Run, Default}, - {"No Space Left On Device", day7.Run, Default}, - {"Treetop Tree House", day8.Run, Default}, - {"Rope Bridge", day9.Run, day9.ConfigureCommand}, - {"Cathode-Ray Tube", day10.Run, day10.ConfigureCommand}, - {"Monkey in the Middle", day11.Run, day11.ConfigureCommand}, - {"Hill Climbing Algorithm", day12.Run, day12.ConfigureCommand}, -} - -func init() { - for index, day := range days { - run := day.run - cmd := &cobra.Command{ - Use: fmt.Sprintf("day%d", index + 1), - Short: day.short, - Run: func(cmd *cobra.Command, args []string) { - err := run(useSampleInput) - if err != nil { - fmt.Printf("Error: %v", err) - os.Exit(1) - } - }, - } - day.configureCommand(cmd) - rootCmd.AddCommand(cmd) - } -} diff --git a/cmd/root.go b/cmd/root.go deleted file mode 100644 index 1545cbb..0000000 --- a/cmd/root.go +++ /dev/null @@ -1,28 +0,0 @@ -package cmd - -import ( - "os" - - "github.com/spf13/cobra" -) - -// If `true` uses the sample input for the day -var useSampleInput bool - -var rootCmd = &cobra.Command{ - // XXX: `go build` bases the name on the module name, and changing that breaks people using `go get`. - // Not worth the effort right now. - Use: "2022", - Short: "Run the days of AoC 2022", -} - -func Execute() { - err := rootCmd.Execute() - if err != nil { - os.Exit(1) - } -} - -func init() { - rootCmd.PersistentFlags().BoolVar(&useSampleInput, "sample", true, "Use the sample input for the day") -} diff --git a/days/1/day1.go b/days/1/day1.go deleted file mode 100644 index 58f6ea3..0000000 --- a/days/1/day1.go +++ /dev/null @@ -1,101 +0,0 @@ -package _1 - -import ( - _ "embed" - "fmt" - "sort" - "strconv" - "strings" - - "github.com/ankon/adventofcode/2022/days" -) - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -type topN struct { - data []int -} - -func makeTopN(n int) topN { - data := make([]int, 0, n) - return topN{data} -} - -// Insert inserts the given value if it fits (i.e. either there is capacity left, or it is bigger than at least one existing value). -func (t *topN) Insert(v int) bool { - l := len(t.data) - - // Find the insert point - at := sort.Search(l, func(i int) bool { return v >= t.data[i] }) - - // No space to add it, and not big enough to shift something out. - if at == cap(t.data) { - return false - } - - // We might not be using all of the capacity yet, expand the array - dropAtEnd := 1 - if l < cap(t.data) { - t.data = append(t.data, 0) - dropAtEnd = 0 - } - - // Shift things if the insert point is not at the end - shiftLen := l - at - dropAtEnd - if shiftLen > 0 { - copy(t.data[at+1:at+1+shiftLen], t.data[at:at+shiftLen]) - } - t.data[at] = v - return true -} - -func (t *topN) Iterate() []int { - return t.data -} - -func findHighestCaloriesOnElf(input string, n int) (int, error) { - topN := makeTopN(n) - - var current int - for _, line := range strings.Split(input, "\n") { - if line == "" { - topN.Insert(current) - current = 0 - } else { - calories, err := strconv.ParseInt(line, 0, 0) - if err != nil { - return 0, err - } - current += int(calories) - } - } - - result := 0 - for _, calories := range topN.Iterate() { - result += calories - } - return result, nil -} - - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - - highest, err := findHighestCaloriesOnElf(input, 1) - if err != nil { - return err - } - fmt.Printf("Highest calorie count on an elf: %d\n", highest) - - highest3, err := findHighestCaloriesOnElf(input, 3) - if err != nil { - return err - } - fmt.Printf("Sum of the 3 highest calorie counts on an elf: %d\n", highest3) - - return nil -} diff --git a/days/1/input.txt b/days/1/input.txt deleted file mode 100644 index 96dba2d..0000000 --- a/days/1/input.txt +++ /dev/null @@ -1,2246 +0,0 @@ -9057 -8878 -2753 -7027 -3880 -7154 -8022 -6710 -5721 - -4863 -3690 -3333 -1831 -5293 -6258 -1212 -4255 -2331 -3785 -1505 -3355 -3353 -4416 - -5918 -3076 -2145 -2712 -6087 -4310 -1084 -5807 -1342 -2770 -5095 -4696 -5842 -4555 -5388 - -20770 - -3968 -15647 -3933 -15427 -16179 - -40721 - -5837 -4419 -2159 -5173 -5215 -1991 -4842 -5642 -5435 -2853 -1055 -1667 -4361 -2316 -1974 - -24315 -6376 -6153 - -3142 -4989 -8864 -3819 -9260 -1273 -2773 - -9320 -4936 -3707 -2103 -8804 -10586 -2018 -3779 - -4129 -1019 -5054 -9429 -10526 -6314 - -13364 -14437 -14046 -7931 -11712 - -2615 -9583 -7471 -3552 -7532 -5797 -1528 -6479 -2595 - -8758 -1774 -3734 -5159 -7046 -2195 -9245 - -12116 -3801 -10950 -1935 -11450 -1091 -5891 - -7792 -4901 -9062 -8640 -6065 -6405 -3606 -2487 -6606 - -5460 -3272 -1310 -1439 -3753 -3947 -4472 -4155 -2056 -2435 -2235 -3662 -2933 -1110 -1024 - -1590 -6814 -12646 -1548 -13624 -5239 - -3955 -2469 -3104 -1548 -4551 -2307 -4450 -4491 -2233 -4706 -5950 -3395 -6592 - -17731 -18903 - -6164 -7718 -7297 -3277 -3592 -3462 -7405 -6164 -2559 -5171 -3337 - -4797 -9455 -13275 -5801 -12597 -2687 - -3091 -1153 -1733 -5022 -4441 -3163 -2375 -6388 -6061 -1444 -3255 -5828 -4414 -6171 - -2841 -17670 -14820 - -2600 -2598 -14037 -10164 - -10425 -4618 -7656 -6910 -8761 -11429 -11611 - -2787 -4826 -1527 -5024 -4252 -1393 -6744 -5665 -4601 -4129 - -6876 -8156 -7854 -6190 -5234 -8616 -1414 -1076 -5161 - -6343 -7372 -7806 -2309 -7352 -7249 -4239 -5572 -7220 -3920 -6979 - -11380 -9322 -10505 -1250 -1122 -1996 -5199 - -7569 -12600 -14729 -2514 -6841 - -9414 -9386 -10521 -4974 -11016 -11238 -1334 - -21696 -27477 - -11623 -11309 -7708 -6139 -2284 -2789 -4566 - -16850 -5171 -7647 -5516 - -24499 - -4040 -7221 -3197 -7251 -8117 -2221 -1881 -5914 -8381 - -3786 -2055 -5301 -4144 -2543 -1406 -5609 -5064 -2447 -4892 -2306 -1654 -1650 -3528 - -4187 -2576 -11910 -8331 -11613 -9093 -2752 - -4166 -6057 -4585 -1942 -5747 -3102 -2501 -4831 -5681 -6596 -4455 -1125 -4887 - -2083 -10447 -16506 - -4971 -3313 -1821 -1493 -5920 -3617 -4857 -3995 -5608 -3679 -1463 -3539 -2600 -3574 -2636 - -2804 -17188 -6966 -15585 - -13184 -15490 -9948 -14350 -12788 - -31669 - -3318 -2544 -7560 -2170 -9138 -2905 -7010 - -3933 -4835 -4704 -2140 -1896 -4951 -3870 -4241 -2819 -1065 -3605 -5667 -2361 -2642 -1926 - -6614 -3288 -3982 -7283 -7086 -2308 -3237 -7365 -6767 -6931 -5417 -5180 - -40453 - -4946 -4257 -2590 -5342 -3880 -6297 -1472 -2441 -4054 -3490 -5054 - -26102 -29920 - -3726 - -18600 -1537 -7197 -3487 - -8193 -8147 -5901 -1975 -3872 -8834 -1623 -6604 - -4501 -3385 -5321 -6771 -2517 -3943 -2744 -1330 -2277 -2344 -6399 -2090 -3571 - -8236 -6575 -6362 -3878 -7021 -8613 -3520 -3424 -2606 -5607 - -10326 -9793 -3341 -7238 -3008 -8188 -11807 - -3755 -16826 -7885 -11677 - -5980 -6793 -2393 -5757 -2525 -6496 -6420 -6902 -6755 -1023 -4226 -1451 -5006 - -6122 -3263 -4273 -2775 -2251 -1076 -2995 -5662 -4189 -2687 -5552 -6586 -2418 - -9994 -10470 -7802 -9572 -9292 -8390 -8803 -4013 - -28290 - -3210 -9126 -1346 -7538 -11536 -10544 -7409 - -20799 -16110 - -3374 -3818 -1924 -1637 -3258 -5224 -4741 -2689 -1455 -5948 -4813 -3549 -2772 -2562 -4358 - -6843 -10575 -7103 -9314 -9901 -3356 -9120 -4552 - -7709 -3977 -6868 -4640 -4665 -7109 -2662 -5682 -5388 -4256 -7249 - -69796 - -8596 -1275 -2723 -2202 -5544 -3687 -4055 -3062 -4137 -4407 - -4870 -2559 -2177 -5239 -1059 -4440 -2536 -1728 -1520 -2572 -2977 -6815 -4679 - -9042 -8883 -2705 -16255 -7889 - -2318 -4232 -1042 -3075 -6202 -7568 -2519 -5918 -1812 -3750 -3845 - -13323 -33324 - -13742 -1087 -17146 -14863 - -2686 -4132 -5052 -4751 -4695 -4528 -4801 -5741 -6027 -1754 -5633 -2427 -4679 -5777 -3143 - -1533 -4361 -2196 -10184 -3981 -6223 -9273 - -1296 -11261 -5647 -8657 -7235 -1788 - -3467 -5537 -10807 -4793 -3452 -12209 - -5745 -5137 -4002 -4824 -2655 -7597 -5748 -5931 -5264 -4469 -8009 - -4436 -4866 -3784 -5181 -6240 -6027 -3343 -5780 -2258 -6389 -3827 -6496 -6378 -4831 - -5894 -7587 -6913 -10950 -6733 -5617 -8084 - -2446 -5375 -4555 -5327 -1233 -2773 -2701 -5454 -3377 -1217 -5889 -6168 -1056 - -3468 -2402 -7848 -5652 -1448 -1954 -1021 -7860 -4305 - -2234 -17391 -5472 - -2028 -5812 -3091 -5508 -5531 -3554 -3706 -2667 -5670 -4845 -2749 -5569 -4811 -3090 -1063 - -2144 -5088 - -20000 -9957 -9049 -3092 - -12235 -6601 -3496 -16002 -1378 - -8800 -1236 -5552 -5693 -8482 -3003 -1126 -4612 -5833 -8430 - -6223 -4640 -1392 -2667 -1602 -2308 -4433 -4148 -6467 -1817 -2926 -3884 -6015 - -2273 -3007 -4509 -2902 -4170 -2731 -4409 -4873 -4237 -2667 -4243 -5788 -3673 -4582 -4696 - -27388 -26736 - -44158 - -4877 -2172 -5968 -1222 -6456 -6920 -3593 -3631 -7213 -3968 -2398 -7264 - -7126 -30978 - -4024 -2766 -2721 -2774 -2807 -1584 -2429 -3517 -5260 -4234 -2381 -5066 -4204 -4737 -4031 - -1528 -2205 -4533 -5873 -1587 -2708 -4198 -5560 -3413 -4058 -1799 -1088 -4285 -6233 - -44226 - -12933 -6090 -14830 - -5766 -2184 -2552 -4757 -1895 -2328 -1265 -5829 -2645 -6110 -6499 -5920 -6421 -2505 - -5039 -6271 -5081 -10068 -3856 -7103 - -5441 -2606 -1249 -2526 -1241 -1914 -3734 -4464 -3855 -4761 -5528 -1419 -2772 -1825 - -3554 - -8766 -2123 -7372 -7752 -6260 -5632 -3802 -9546 -7769 - -9108 -4838 - -1374 -3720 -7558 -4646 -6793 -4704 -3361 -8038 -6147 -2160 -1983 - -3133 -3621 -6073 -2533 -1644 -5277 -4276 -1921 -6251 -5273 -1571 -3769 -2155 - -2721 -3793 -4935 -2950 -2399 -1083 -4213 -4958 -1139 -1140 -2454 -3291 -3865 -1667 -4798 - -5676 -5904 -1356 -1439 -3241 -2933 -4164 -3887 -4712 -2759 -4390 -1274 -6220 -2557 - -2049 -4787 -1819 -3172 -5511 -1006 -1373 -6094 -3054 -4914 -6057 -4883 -2867 -5363 -3916 - -11348 -3724 -6793 -7336 -4032 -11297 - -4231 -4277 -2982 -2408 -5673 -6805 -4710 -7659 -6866 - -2950 -4018 -6167 -8316 -7308 -4955 -8341 -1512 -3167 -8493 - -15665 -14654 -1249 -15313 -4636 - -1494 -3325 -5902 -1393 -6813 -3900 -2827 -5936 -6589 -6847 -4658 - -11492 -14548 -5203 -15187 -5937 - -1358 -2801 -1086 -5190 -4022 -5013 -3511 -4398 -1774 -2194 -1887 -5704 -2012 -1259 - -4763 -2250 -6915 -4281 -1246 -7242 -6049 -5113 -1187 -2486 -6688 -3275 - -22345 -1336 -11325 - -6000 -3641 -1082 -2924 -5477 -3336 -4126 -3981 -5359 -1053 -4299 -5952 -4655 - -46233 - -17242 -6366 -7866 - -12504 -4031 -12664 -9756 -12750 - -3373 - -3091 -11142 -15034 -1144 -11747 - -3129 -2007 -8482 -7205 -7734 -8770 -2213 -5582 -5437 -3223 - -4471 -2591 -3286 -4446 -5388 -3600 -3357 -2644 -5028 -5569 -5055 -3284 -5597 -4116 -1076 - -3792 -2354 -8030 -3269 -2483 -1302 -7427 -6148 -3836 -7834 -1663 - -2930 -5964 -1707 -2899 -4160 -2193 -2705 -5799 -4612 -2741 -2333 -4969 -3117 -5276 -1747 - -62287 - -4321 -22825 -5690 - -7287 -1774 -4464 -2273 -2903 -8920 -4092 -8072 -8763 - -8885 -7470 -3145 -3523 -5647 -1067 -3048 - -6923 -6463 -4032 -5923 -1982 -4331 -6323 -1192 -5583 -5470 -6476 -5889 -2991 - -6697 -1560 -5520 -4516 -4845 -3035 -6047 -4906 -4596 -1934 -7245 -4476 - -4001 -7227 -5720 -3195 -8505 -6612 -4012 -4050 -8659 -3804 - -8332 -3362 -4926 -4307 -4779 -1856 -7350 -4068 -8592 -2415 - -60630 - -4263 -1716 -8004 -5253 -2004 -5381 -5614 -3020 -5985 -5587 -3563 - -18645 -10906 -3077 -2255 - -59591 - -3203 -7739 -2234 -1421 -3353 -5031 -6395 -5614 - -6259 -8748 -4341 -7788 -1074 -8497 -3996 -1294 -5197 -5779 - -10765 -5009 -3541 -2298 -10698 -13317 - -6181 -1305 -6527 -2125 -9085 -2889 -8794 -3265 -4166 - -3607 -1912 -1927 -6455 -1043 -6949 -2542 -1552 -3064 -2009 -6587 - -5574 -4632 -5869 -4312 -1703 -6124 -6479 -4556 -5917 -5890 -4949 -5614 -5576 - -2267 -7221 -5412 -5721 -2931 -3149 -6934 -3520 -6237 -4317 -1295 -6450 - -12143 -7105 -2050 -9391 -3017 -10750 - -4649 -2052 -1856 -3055 -2132 -6630 -5964 -5505 -3395 -2080 - -4388 -6963 -2613 -1055 -6588 -1348 -3752 -5538 -4524 -7994 -3977 - -5444 -6078 -8572 -10427 -5423 -3812 -1984 - -9248 -17691 -12948 -17445 - -5807 -3737 -5304 -1495 -5162 -1178 -6053 -5597 -5645 -2267 -4333 -3455 -4086 -2024 -4127 - -5502 -3665 -3494 -1502 -4702 -4563 -5216 -6486 -1931 -6493 -4618 -3960 -1149 -5109 - -2198 -1411 -4511 -1913 -4173 -4446 -6176 -2305 -4748 -4560 -4048 -5361 -4481 - -30924 - -15726 -4014 -20018 -2880 - -3345 -2576 -4787 -2186 -2156 -2989 -4400 -5147 -5393 -2830 -5869 -4839 -2860 -2134 - -2400 -2009 -2634 -4431 -7342 -5534 -2072 -5520 -5518 -2998 -3686 -4906 - -10948 -12532 -11104 -7815 - -5883 -6111 -4117 -3590 -3295 -3984 -2950 -6814 -1123 -4642 -1770 -2029 -4406 - -19302 -1549 -10378 -13976 - -4852 -7261 -4206 -12867 -8400 -11611 - -2587 -3559 -1415 -5308 -3732 -6752 -3804 -1720 -2570 -5106 -6658 -5105 -6156 - -7380 -10456 -8378 -10778 -9788 -1299 -10299 - -3596 -5969 -8288 -3025 -8196 -6410 -5966 -3060 -3015 -1270 - -14103 -5510 -13362 -19169 - -3056 -3546 -7784 -2262 -3791 -3159 -5386 -6489 -3421 -7995 -4498 - -27239 - -9345 -8921 -5252 -1154 -3189 -1175 -3216 -3282 -9392 - -2821 -7731 -8002 -1351 -5951 -4544 -3688 -4855 -8082 -1428 -5613 - -6506 -2529 -6614 -3938 -4404 -5581 -1984 -6242 -7589 - -8393 -6631 -5200 -9914 -10229 -2405 -3933 -9333 - -6766 -3486 -11457 -3098 - -5091 -4105 -1368 -4682 -3094 -4077 -5876 -1958 -1641 -3925 -2969 -3780 -5489 - -10434 -2285 -2830 -6976 -3561 -6756 - -3944 -2998 -1874 -4642 -4634 -2155 -2221 -2270 -2446 -1514 -5382 -4333 -5441 -2412 -1789 - -2433 -4036 -6005 -1551 -7281 -8466 -2141 -4190 - -5103 -6956 -5839 -2237 -7177 -6397 -11533 - -7100 -3476 -4592 -6502 -3322 -10524 -2973 -10712 - -3440 -1323 -1316 -1979 -1168 -6432 -3512 -5739 -2131 -4504 -5233 -3726 -6371 -6125 - -1917 -3442 -4104 -6123 -1657 -3139 -1690 -3323 -1269 -1407 -5603 -4819 -1787 -2340 - -11143 -9483 -9438 -12565 -7187 -13478 - -6406 -2289 -8029 -1790 -5009 -6300 -2521 - -8040 -6772 -3244 -5246 -6455 -6715 -4024 -3855 -6458 -4945 -4207 - -4628 -4872 -3344 -5675 -3761 -4467 -5113 -5746 -4140 - -9532 -1992 -5741 -8559 -4606 -6310 -5183 - -7530 -13402 -8481 -8327 - -17909 -7813 -12567 -9674 - -3329 -6032 -5539 -5513 -2555 -4767 -1085 -3329 -5138 -4448 -4082 -5569 -2732 -3326 - -2019 -3327 -3701 -3145 -1943 -1467 -1913 -5141 -7475 -7026 -4964 -2353 - -3375 -1186 -2890 -1248 -5696 -5993 -3804 -1133 -2035 -5068 -4280 -2123 -1890 - -8675 -10684 -22636 - -2704 -1093 -9357 -7940 -4843 -1118 -5533 -8943 -6492 - -67791 - -7101 -3406 -8840 -3652 -9258 -5329 -4562 -5314 -9146 - -3673 -13526 -2792 -5659 -13396 -8400 - -2492 -5265 -5244 -2173 -5032 -1182 -1486 -4561 -4673 -2480 -5148 -1375 -1093 - -1368 -5899 -6527 -7584 -2148 -2960 -7701 -5381 -6149 -2589 -7496 - -12206 -11842 -11444 -12447 - -3417 -5044 -7116 -5491 -9020 -8610 -1047 -5725 -2712 - -9153 -1836 -3337 -1686 -6044 -8786 -7476 -1688 - -17559 -10138 -16446 - -15625 -16403 -16979 -7402 - -3561 -2910 -12805 -8128 -13171 -5786 - -1332 - -1135 -5954 -9216 -5471 -3494 -9353 -6330 -4152 - -2031 -2180 -1544 -2509 -3894 -2882 -1460 -6647 -4655 -3164 -6691 -2156 -5754 - -2309 -5397 -6055 -5585 -9712 -9731 -9274 - -9865 -7291 -4863 -10688 -4135 -4572 -7321 -5603 - -1428 -5533 -4032 -1648 -1676 -5556 -1186 -4594 -5915 -2477 -4923 -5393 -2101 -2509 -1250 - -2388 -2255 -3768 -5340 -4357 -5600 -4198 -6423 -5974 -5673 -3717 -3275 -5871 -3250 - -11192 -1266 -3583 -10707 -11653 -3264 -6641 - -2009 -12343 -2394 -2147 -1560 -4352 - -5152 -6000 -6725 -3479 -1229 -1599 -3971 -6829 -8654 - -7486 -15798 -2011 -9551 -15283 - -8934 -27039 - -2048 -7506 -3661 -7298 -8557 -6387 -6496 -4471 -8596 -5325 - -1760 -2615 -1038 -9295 -6394 -7329 -5015 -4727 -9584 - -40347 - -5992 -9771 -14112 - -13049 -14348 -13202 -10630 -9351 - -8778 -9152 -10173 -8648 -4552 -4300 -5921 -9924 - -26578 -34718 - -2974 -3130 -4319 -4116 -3484 -5362 -5583 -2885 -4526 -2756 -5977 -2629 -2429 -1755 -1278 - -2848 -4821 -2207 -6922 -6699 -1999 -2354 -1922 -2133 -4496 -2510 -6509 -6929 - -5345 -3244 -2145 -1243 -1245 -2210 -5939 -3311 -6482 -5700 -3395 -2508 -3893 -6405 - -3618 -2718 -4854 -1334 -3478 -3043 -3466 -1028 -2627 -3873 -4878 -5160 -6017 -4880 -1342 - -9909 -7167 -7465 -7787 -10618 -6259 -3751 -1488 - -24782 -13684 -1905 - -5325 -9319 -7321 -6398 -8841 -3773 -2807 -9032 -2572 - -5346 -7500 -8693 -9429 -1728 -1303 -2467 -3959 -8196 - -6220 -6193 -4246 -3802 -6433 -4710 -3059 -2880 -6077 -1924 -5892 - -3421 -1973 -9474 -3990 -15878 - -6757 -9558 -9440 -8896 -5221 -3819 -6669 -1578 -7307 - -2015 -5934 -2351 -4738 -6504 -1748 -5112 -4067 -1623 -1944 -6297 -3300 -1089 - -1757 -4617 -8124 -6837 -4685 -9532 -11427 - -9094 -6552 -3882 -5341 -10752 -5572 -5882 - -5806 -3599 -1885 -4608 -6756 -4656 -1160 -4783 -2759 -3006 -3044 -5491 -6877 - -6295 -18921 -23198 - -2201 -2488 -1050 -1414 -2799 -3883 -7092 -4746 -3719 -3211 -1548 - -2656 -3600 -5148 -2300 -5547 -8226 -6952 -2611 -2268 -6490 - -5499 -8937 -12091 -1429 -9253 -2187 -2660 - -12898 - -3536 -3120 -6811 -2427 -2710 -2100 -2030 -7003 -3932 -3514 -6390 -6017 - -7645 -3909 -2219 -2290 -1401 -1812 -3180 -7733 -2547 -2653 diff --git a/days/1/sample.txt b/days/1/sample.txt deleted file mode 100644 index 2094f91..0000000 --- a/days/1/sample.txt +++ /dev/null @@ -1,14 +0,0 @@ -1000 -2000 -3000 - -4000 - -5000 -6000 - -7000 -8000 -9000 - -10000 diff --git a/days/10/day10.go b/days/10/day10.go deleted file mode 100644 index 1a7ed18..0000000 --- a/days/10/day10.go +++ /dev/null @@ -1,120 +0,0 @@ -package _10 - -import ( - _ "embed" - "fmt" - "strconv" - "strings" - - "github.com/ankon/adventofcode/2022/days" - "github.com/spf13/cobra" -) - -var trivialInput = ` - noop - addx 3 - addx -5` - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -var debug = false - -func ConfigureCommand(cmd *cobra.Command) { - cmd.Flags().BoolVar(&debug, "debug", false, "Enable debug output") -} - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - instructions := strings.Split(strings.TrimSpace(input), "\n") - - sum := 0 - sampleTask1 := func(cycle int, state state) { - if debug { - fmt.Printf("%d: X=%d\n", cycle, state.x) - } - if cycle == 20 || cycle == 60 || cycle == 100 || cycle == 140 || cycle == 180 || cycle == 220 { - sum += cycle * state.x - } - } - err := simulateProgram(instructions, state{1}, sampleTask1) - if err != nil { - return err - } - fmt.Printf("Signal strength sum %d\n", sum) - - lines := []string{} - line := "" - pos := 0 - crt := func(cycle int, state state) { - if debug { - fmt.Printf("%d: Sprite at %d, drawing pos %d\n", cycle, state.x, pos) - fmt.Printf("%d: %s\n", cycle, line) - } - - if state.x-1 <= pos && state.x+1 >= pos { - line += "#" - } else { - line += "." - } - pos++ - - if cycle%40 == 0 { - lines = append(lines, line) - line = "" - pos = 0 - } - } - err = simulateProgram(instructions, state{1}, crt) - if err != nil { - return err - } - fmt.Printf("CRT %d\n", sum) - for _, line := range lines { - fmt.Println(line) - } - - return nil -} - -type state struct { - x int -} - -func simulateProgram(instructions []string, initialState state, sample func(cycle int, state state)) error { - cycle := 1 - state := initialState - - tick := func() { - sample(cycle, state) - cycle++ - } - - for _, ins := range instructions { - op, arg, _ := strings.Cut(ins, " ") - - switch op { - case "noop": - tick() - case "addx": - tick() - - tick() - v, err := strconv.Atoi(arg) - if err != nil { - return fmt.Errorf("invalid arg %q to addx at %d", arg, cycle) - } - state.x += v - default: - return fmt.Errorf("invalid op %q at %d", op, cycle) - } - } - - // One more tick, to sample the end state - tick() - - return nil -} diff --git a/days/10/input.txt b/days/10/input.txt deleted file mode 100644 index 57f49a0..0000000 --- a/days/10/input.txt +++ /dev/null @@ -1,139 +0,0 @@ -noop -noop -noop -addx 6 -addx -1 -noop -addx 5 -noop -noop -addx -12 -addx 19 -addx -1 -noop -addx 4 -addx -11 -addx 16 -noop -noop -addx 5 -addx 3 -addx -2 -addx 4 -noop -noop -noop -addx -37 -noop -addx 3 -addx 2 -addx 5 -addx 2 -addx 10 -addx -9 -noop -addx 1 -addx 4 -addx 2 -noop -addx 3 -addx 2 -addx 5 -addx 2 -addx 3 -addx -2 -addx 2 -addx 5 -addx -40 -addx 25 -addx -22 -addx 2 -addx 5 -addx 2 -addx 3 -addx -2 -noop -addx 23 -addx -18 -addx 2 -noop -noop -addx 7 -noop -noop -addx 5 -noop -noop -noop -addx 1 -addx 2 -addx 5 -addx -40 -addx 3 -addx 8 -addx -4 -addx 1 -addx 4 -noop -noop -noop -addx -8 -noop -addx 16 -addx 2 -addx 4 -addx 1 -noop -addx -17 -addx 18 -addx 2 -addx 5 -addx 2 -addx 1 -addx -11 -addx -27 -addx 17 -addx -10 -addx 3 -addx -2 -addx 2 -addx 7 -noop -addx -2 -noop -addx 3 -addx 2 -noop -addx 3 -addx 2 -noop -addx 3 -addx 2 -addx 5 -addx 2 -addx -5 -addx -2 -addx -30 -addx 14 -addx -7 -addx 22 -addx -21 -addx 2 -addx 6 -addx 2 -addx -1 -noop -addx 8 -addx -3 -noop -addx 5 -addx 1 -addx 4 -noop -addx 3 -addx -2 -addx 2 -addx -11 -noop -noop -noop diff --git a/days/10/sample.txt b/days/10/sample.txt deleted file mode 100644 index 37ee8ee..0000000 --- a/days/10/sample.txt +++ /dev/null @@ -1,146 +0,0 @@ -addx 15 -addx -11 -addx 6 -addx -3 -addx 5 -addx -1 -addx -8 -addx 13 -addx 4 -noop -addx -1 -addx 5 -addx -1 -addx 5 -addx -1 -addx 5 -addx -1 -addx 5 -addx -1 -addx -35 -addx 1 -addx 24 -addx -19 -addx 1 -addx 16 -addx -11 -noop -noop -addx 21 -addx -15 -noop -noop -addx -3 -addx 9 -addx 1 -addx -3 -addx 8 -addx 1 -addx 5 -noop -noop -noop -noop -noop -addx -36 -noop -addx 1 -addx 7 -noop -noop -noop -addx 2 -addx 6 -noop -noop -noop -noop -noop -addx 1 -noop -noop -addx 7 -addx 1 -noop -addx -13 -addx 13 -addx 7 -noop -addx 1 -addx -33 -noop -noop -noop -addx 2 -noop -noop -noop -addx 8 -noop -addx -1 -addx 2 -addx 1 -noop -addx 17 -addx -9 -addx 1 -addx 1 -addx -3 -addx 11 -noop -noop -addx 1 -noop -addx 1 -noop -noop -addx -13 -addx -19 -addx 1 -addx 3 -addx 26 -addx -30 -addx 12 -addx -1 -addx 3 -addx 1 -noop -noop -noop -addx -9 -addx 18 -addx 1 -addx 2 -noop -noop -addx 9 -noop -noop -noop -addx -1 -addx 2 -addx -37 -addx 1 -addx 3 -noop -addx 15 -addx -21 -addx 22 -addx -6 -addx 1 -noop -addx 2 -addx 1 -noop -addx -10 -noop -noop -addx 20 -addx 1 -addx 2 -addx 2 -addx -6 -addx -11 -noop -noop -noop diff --git a/days/11/README.md b/days/11/README.md deleted file mode 100644 index 99fc0df..0000000 --- a/days/11/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Ideas - -## Use unique prime factors - -Doesn't work, because the additions break. See the [2022_11_2-prime-factors branch]. - -## Modulo Arithmetics - -Secretly this was already obvious, but I don't like these. Still, probably what could work and is worth a try is simply to store everything modulo the product of the divisors. - -TODO: Verify that this is "mathematically sane". It should work for the additions, but ... diff --git a/days/11/day11.go b/days/11/day11.go deleted file mode 100644 index 23db4b7..0000000 --- a/days/11/day11.go +++ /dev/null @@ -1,269 +0,0 @@ -package _11 - -import ( - _ "embed" - "fmt" - "strconv" - "strings" - - "github.com/ankon/adventofcode/2022/days" - "github.com/ankon/adventofcode/2022/utils" - "github.com/spf13/cobra" - "golang.org/x/exp/slices" -) - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -var debug = 0 -var rounds = 20 -var relief = true - -// The modulo to use for arithmetics, calculated from the divisors of the monkey test functions -var modulo = 1 - -func ConfigureCommand(cmd *cobra.Command) { - cmd.Flags().IntVar(&debug, "debug", debug, "Enable debug output (higher numbers mean more output)") - cmd.Flags().IntVar(&rounds, "rounds", rounds, "Number of rounds (20 for task 1, 10000 for task 2)") - cmd.Flags().BoolVar(&relief, "relief", relief, "Feel relief after inspection (true for task 1, false for task 2)") -} - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - lines := strings.Split(strings.TrimSpace(input), "\n") - - monkeys, err := parseMonkeys(lines) - if err != nil { - return err - } - - activities := countItemInspections(monkeys, rounds) - slices.Sort(activities) - mostActivities := activities[len(activities)-1] - secondMostActivities := activities[len(activities)-2] - - fmt.Printf("inspections: %d * %d = %d\n", mostActivities, secondMostActivities, mostActivities*secondMostActivities) - - return nil -} - -type opFunc func(int) int - -type monkey struct { - // Items the monkey has (only tracking the worry level) - items []int - - op opFunc - - divisor int - testTrueMonkey int - testFalseMonkey int - - inspections int -} - -func (m *monkey) inspectItem() (int, bool) { - if len(m.items) == 0 { - return 0, false - } - result := m.items[0] - m.items = m.items[1:] - m.inspections++ - return result, true -} - -func (m *monkey) catchItem(level int) { - m.items = append(m.items, level) -} - -const startItemsPrefix = " Starting items: " -const opPrefix = " Operation: new = " -const testDivisibleByPrefix = " Test: divisible by " -const testIfTrueThrowPrefix = " If true: throw to monkey " -const testIfFalseThrowPrefix = " If false: throw to monkey " - -func parseMonkey(lines []string) (monkey, int, error) { - items := []int{} - var op opFunc - var divisor int - var testTrueMonkey int - var testFalseMonkey int - - i := 0 - for ; i < len(lines); i++ { - line := lines[i] - if line == "" { - break - } else if strings.HasPrefix(line, startItemsPrefix) { - ss := strings.Split(line[len(startItemsPrefix):], ",") - for _, s := range ss { - v, err := strconv.Atoi(strings.TrimSpace(s)) - if err != nil { - return monkey{}, i, fmt.Errorf("cannot parse starting items %q", ss) - } - items = append(items, v) - } - } else if strings.HasPrefix(line, opPrefix) { - ss := strings.Split(line[len(opPrefix):], " ") - arg2, _ := strconv.Atoi(ss[2]) - - switch ss[1] { - case "+": - if ss[0] != "old" { - return monkey{}, i, fmt.Errorf("first operand must be %q for +", "old") - } - if ss[2] == "old" { - return monkey{}, i, fmt.Errorf("second operand must not be %q for +", ss[2]) - } - op = func(item int) int { - return (item + arg2) % modulo - } - case "*": - if ss[0] != "old" { - return monkey{}, i, fmt.Errorf("first operand must be %q for *", "old") - } - if ss[2] != "old" && !utils.IsPrime(arg2) { - return monkey{}, i, fmt.Errorf("second operand must be %q or prime for *", "old") - } - op = func(item int) int { - if ss[2] == "old" { - return int(utils.MultiplyMod(uint64(item), uint64(item), uint64(modulo))) - } else { - return int(utils.MultiplyMod(uint64(item), uint64(arg2), uint64(modulo))) - } - } - default: - return monkey{}, i, fmt.Errorf("unsupported operator %q", ss[1]) - } - } else if strings.HasPrefix(line, testDivisibleByPrefix) { - v, err := strconv.Atoi(line[len(testDivisibleByPrefix):]) - if err != nil { - return monkey{}, i, fmt.Errorf("cannot parse test %q", line) - } - divisor = v - - ifTrueLine := lines[i+1] - v, err = strconv.Atoi(ifTrueLine[len(testIfTrueThrowPrefix):]) - if err != nil { - return monkey{}, i, fmt.Errorf("cannot parse expected true condition %q", ifTrueLine) - } - testTrueMonkey = v - - ifFalseLine := lines[i+2] - v, err = strconv.Atoi(ifFalseLine[len(testIfFalseThrowPrefix):]) - if err != nil { - return monkey{}, i, fmt.Errorf("cannot parse expected false condition %q", ifFalseLine) - } - testFalseMonkey = v - - i += 2 - } - } - - return monkey{items, op, divisor, testTrueMonkey, testFalseMonkey, 0}, i, nil -} - -func parseMonkeys(lines []string) ([]*monkey, error) { - result := []*monkey{} - for l := 0; l < len(lines); l++ { - line := lines[l] - if strings.TrimSpace(line) == "" { - continue - } - - id := 0 - n, err := fmt.Sscanf(line, "Monkey %d:", &id) - if err != nil { - return nil, fmt.Errorf("cannot parse monkey line at %d", l) - } - if n != 1 { - return nil, fmt.Errorf("expected monkey line at %d", l) - } - if id != len(result) { - return nil, fmt.Errorf("expected monkey id %d, but got %d at %d", len(result), id, l) - } - - m, consumed, err := parseMonkey(lines[l+1:]) - if err != nil { - return nil, err - } - result = append(result, &m) - - l += consumed - - // XXX: Can we do this nicer? - modulo *= m.divisor - } - - return result, nil -} - -func playRound(monkeys []*monkey) { - for i, m := range monkeys { - if debug > 2 { - fmt.Printf("Monkey %d:\n", i) - } - for { - item, ok := m.inspectItem() - if !ok { - break - } - - if debug > 2 { - fmt.Printf(" Monkey inspects an item with a worry level of %d.\n", item) - } - - level := m.op(item) - if debug > 2 { - fmt.Printf(" Worry level is now %d.\n", level) - } - - if relief { - level /= 3 - if debug > 2 { - fmt.Printf(" Monkey gets bored with item. Worry level is divided by 3 to %d.\n", level) - } - } - - var throwTo int - if level%m.divisor == 0 { - throwTo = m.testTrueMonkey - } else { - throwTo = m.testFalseMonkey - } - if debug > 2 { - fmt.Printf(" Item with worry level %d is thrown to monkey %d.\n", level, throwTo) - } - - monkeys[throwTo].catchItem(level) - } - } -} - -func countItemInspections(monkeys []*monkey, rounds int) []int { - for round := 1; round <= rounds; round++ { - playRound(monkeys) - - if debug > 1 { - fmt.Printf("After round %d, the monkeys are holding items with these worry levels:\n", round) - for k, m := range monkeys { - fmt.Printf("Monkey %d: %v\n", k, m.items) - } - } - if debug > 0 && (round == 1 || round == 20 || round%1000 == 0) { - fmt.Printf("== After round %d ==\n", round) - for k, m := range monkeys { - fmt.Printf("Monkey %d inspected items %d times.\n", k, m.inspections) - } - } - } - - result := make([]int, len(monkeys)) - for k, m := range monkeys { - result[k] = m.inspections - } - return result -} diff --git a/days/11/input.txt b/days/11/input.txt deleted file mode 100644 index ef22f88..0000000 --- a/days/11/input.txt +++ /dev/null @@ -1,55 +0,0 @@ -Monkey 0: - Starting items: 66, 79 - Operation: new = old * 11 - Test: divisible by 7 - If true: throw to monkey 6 - If false: throw to monkey 7 - -Monkey 1: - Starting items: 84, 94, 94, 81, 98, 75 - Operation: new = old * 17 - Test: divisible by 13 - If true: throw to monkey 5 - If false: throw to monkey 2 - -Monkey 2: - Starting items: 85, 79, 59, 64, 79, 95, 67 - Operation: new = old + 8 - Test: divisible by 5 - If true: throw to monkey 4 - If false: throw to monkey 5 - -Monkey 3: - Starting items: 70 - Operation: new = old + 3 - Test: divisible by 19 - If true: throw to monkey 6 - If false: throw to monkey 0 - -Monkey 4: - Starting items: 57, 69, 78, 78 - Operation: new = old + 4 - Test: divisible by 2 - If true: throw to monkey 0 - If false: throw to monkey 3 - -Monkey 5: - Starting items: 65, 92, 60, 74, 72 - Operation: new = old + 7 - Test: divisible by 11 - If true: throw to monkey 3 - If false: throw to monkey 4 - -Monkey 6: - Starting items: 77, 91, 91 - Operation: new = old * old - Test: divisible by 17 - If true: throw to monkey 1 - If false: throw to monkey 7 - -Monkey 7: - Starting items: 76, 58, 57, 55, 67, 77, 54, 99 - Operation: new = old + 6 - Test: divisible by 3 - If true: throw to monkey 2 - If false: throw to monkey 1 diff --git a/days/11/sample.txt b/days/11/sample.txt deleted file mode 100644 index 30e09e5..0000000 --- a/days/11/sample.txt +++ /dev/null @@ -1,27 +0,0 @@ -Monkey 0: - Starting items: 79, 98 - Operation: new = old * 19 - Test: divisible by 23 - If true: throw to monkey 2 - If false: throw to monkey 3 - -Monkey 1: - Starting items: 54, 65, 75, 74 - Operation: new = old + 6 - Test: divisible by 19 - If true: throw to monkey 2 - If false: throw to monkey 0 - -Monkey 2: - Starting items: 79, 60, 97 - Operation: new = old * old - Test: divisible by 13 - If true: throw to monkey 1 - If false: throw to monkey 3 - -Monkey 3: - Starting items: 74 - Operation: new = old + 3 - Test: divisible by 17 - If true: throw to monkey 0 - If false: throw to monkey 1 diff --git a/days/12/day12.go b/days/12/day12.go deleted file mode 100644 index 6ada2da..0000000 --- a/days/12/day12.go +++ /dev/null @@ -1,222 +0,0 @@ -package _12 - -import ( - _ "embed" - "fmt" - "math" - "sort" - "strings" - - "github.com/ankon/adventofcode/2022/days" - "github.com/spf13/cobra" - "golang.org/x/exp/slices" -) - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -var debug = 0 - -func ConfigureCommand(cmd *cobra.Command) { - cmd.Flags().IntVar(&debug, "debug", debug, "Enable debug output (higher numbers mean more output)") -} - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - m, start, end, err := parseHeightmap(strings.TrimSpace(input)) - if err != nil { - return err - } - - p := m.findPath(start, end) - fmt.Printf("Shortest path: %d steps\n", len(p)-1) - - // Find all possible starting points (elevation = 'a') - shortestPathLen := math.MaxInt - for y := 0; y < m.height(); y++ { - for x := 0; x < m.width(); x++ { - if m[y][x] == byte('a') { - p := m.findPath(point{x, y}, end) - if p != nil && len(p) < shortestPathLen { - shortestPathLen = len(p) - 1 - } - } - } - } - fmt.Printf("Shortest possible path: %d steps\n", shortestPathLen) - - return nil -} - -type point struct { - x, y int -} -type heightmap [][]byte - -type directionSymbol = byte - -const ( - up directionSymbol = byte('^') - right directionSymbol = byte('>') - down directionSymbol = byte('v') - left directionSymbol = byte('<') -) - -type step struct { - point - directionSymbol -} - -type path []step - -func (p *path) show(width, height int) []string { - result := []string{} - for y := 0; y < height; y++ { - line := "" - for x := 0; x < width; x++ { - s := slices.IndexFunc(*p, func(step step) bool { - return step.x == x && step.y == y - }) - if s != -1 { - line += string((*p)[s].directionSymbol) - } else { - line += "." - } - } - result = append(result, line) - } - result = append(result, fmt.Sprintf("%*d", width, len(*p))) - return result -} - -func showMultiplePaths(paths []path, width, height int) { - // XXX: +1 for the length at the end - lines := make([][]string, height+1) - for _, p := range paths { - l := p.show(width, height) - for i, tmp := range l { - lines[i] = append(lines[i], tmp) - } - } - - for _, line := range lines { - fmt.Printf("%s\n", strings.Join(line, " ")) - } -} - -var directions = map[directionSymbol]point{ - up: {0, -1}, - right: {1, 0}, - down: {0, 1}, - left: {-1, 0}, -} - -func (h *heightmap) height() int { - return len(*h) -} -func (h *heightmap) width() int { - return len((*h)[0]) -} - -func (h *heightmap) findPath(start, end point) path { - width := h.width() - height := h.height() - - visited := make([][]bool, height) - for y := 0; y < height; y++ { - visited[y] = make([]bool, width) - } - - // Open paths, sorted by their (current) length - open := []path{ - {step{start, startSymbol}}, - } - visited[start.y][start.x] = true - - for len(open) > 0 { - if debug > 0 { - max := len(open) - if max > 10 { - max = 10 - } - showMultiplePaths(open[:max], width, height) - } - - // Take the last (shortest) one, expand the options, and then insert - // them into the correct place - p := open[len(open)-1] - open = open[:len(open)-1] - - last := p[len(p)-1] - for s, d := range directions { - x := last.x + d.x - if x < 0 || x >= width { - continue - } - y := last.y + d.y - if y < 0 || y >= height { - continue - } - // XXX: We could go down, but should we? - if (*h)[y][x] > (*h)[last.y][last.x]+1 { - continue - } - n := point{x, y} - if !visited[n.y][n.x] { - visited[n.y][n.x] = true - newPath := append(path{}, p...) - newPath = append(newPath, step{n, s}) - newPathLen := len(newPath) - - if n == end { - // Found a result, and we know this is the shortest; if there are multiple - // then it will be at least as short. - return newPath - } - - // Find the point where we can insert the new path - i := sort.Search(len(open), func(i int) bool { - return newPathLen > len(open[i]) - }) - if i == len(open) { - // Put at the end - open = append(open, newPath) - } else { - // Insert _after_ the last element with the same length - for ; i < len(open) && len(open[i]) == newPathLen; i++ { - } - tmp := append([]path{}, open[:i]...) - tmp = append(tmp, newPath) - open = append(tmp, open[i:]...) - } - } - } - } - - return nil -} - -const startSymbol = byte('S') -const endSymbol = byte('E') - -func parseHeightmap(input string) (m heightmap, start point, end point, err error) { - m = [][]byte{} - for y, line := range strings.Split(input, "\n") { - data := []byte(line) - x := slices.Index(data, startSymbol) - if x != -1 { - start = point{x, y} - data[x] = byte('a') - } - x = slices.Index(data, endSymbol) - if x != -1 { - end = point{x, y} - data[x] = byte('z') - } - m = append(m, data) - } - return m, start, end, nil -} diff --git a/days/12/input.txt b/days/12/input.txt deleted file mode 100644 index d469653..0000000 --- a/days/12/input.txt +++ /dev/null @@ -1,41 +0,0 @@ -abcccaaaaaaccccccccaaaaaccccccaaaaaaccccccaaaaaaaacccaaaaaaaccaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa -abcccaaaaaacccccccaaaaaaccccaaaaaaaacccccccaaaaaaaaaaaaaaaaccaaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa -abccccaaaaacaaaccaaaaaaaacccaaaaaaaaacccccccaaaaaaaaaaaaaaaacaaaaaacccccccccaaacccccccccccaaaaaaaaccccccccccaaccccccccccccccccaaaaaa -abccccaaaaccaaaaaaaaaaaaacccaaaaaaaaaacccccaaaaaaaaaaaaaaaaaaacaaaacccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccccccccccccccccccaaa -abcccccccccaaaaaacccaacccccccccaaacaaaccccccaacccccccaaaaaaaaacaacccccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccacaaccccccccccccaaa -abcccccccccaaaaaacccaacccccccccaaacccccccccccccccccccaaaacaaaacccccccaacaaccaaaccccccccccaccaaaaacacccccccccaaaacaaaaccccccccccccaac -abccccccccccaaaaacccccccccccccccacccaaaacccccccccccccaaaacccccccccccccaaaacccccccccccaacccccaaaaccccccccjjjjaaaaaaaaaccccccccccccccc -abccccccccccaaaacccccccccccccccccccaaaaacccccccccccccaaaccccccccccccccaaaaacccccccccaaaaaacccaaccccccccjjjjjjkkaaaacccccccccaacccccc -abcccccaaccccccccccccccccccccccccccaaaaaacccccccccccccaacccccccccccccaaaaaaccccccccccaaaaaccccccccccccjjjjjjjkkkkaacccccaacaaacccccc -abccaaaacccccccccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccaaaacaccccccccaaaaaaaccccaacccccjjjjoooookkkkkkkklllaaaaaaacccc -abccaaaaaacccccccccccccccccccccccccaaaaacccccccccccccccccccccccccccccccaaccccccccccaaaaaaaaccaaaaccccjjjoooooookkkkkkkllllaaaaaacccc -abcccaaaaacccccccccccccccccccccccccccaaaccccccccaaaacccccccccccccccccccccccccccccccaaaaaaaaccaaaaccccjjooooooooppkkppplllllaccaacccc -abccaaaaaccccccccccccaccccccccccccccccccccccccccaaaacccccccccccccccccccccccccccccccccaaacacccaaaacccijjooouuuuoppppppppplllccccccccc -abcccccaacccccccccccaaaaaaaaccccccccccccccccccccaaaaccccaaccccccccaaacccccccccccccaacaaccccccccccccciijoouuuuuuppppppppplllcccaccccc -abcccccccccccccccccccaaaaaaccccccccccccccccccccccaaccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiiiootuuuuuupuuuvvpppllccccccccc -abcccccccccccccccccccaaaaaaccaaaaacccccccccccccccccccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiinnotuuxxxuuuuvvvpppllccccccccc -abccccccccccccccacccaaaaaaaacaaaaaaacccccccccccccccccccaaaacccccccaaacccccaaaaccaaaaaccccaaccccccciiiinnnttxxxxuuyyyvvqqqllccccccccc -abcccccccccccaaaaccaaaaaaaaaaaaaaaaaaccaacccccccccccccccccccccccccccccccccaaaacccaaaaaccaaacccccciiinnnnnttxxxxxyyyyvvqqqllccccccccc -abaaaacccccccaaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccaaaacccaaaaaacaaaccccciiinnnnttttxxxxxyyyyvvqqmmmccccccccc -abaaaaccccccccaaaaacccaaaaacaaaaaacaaaaaaccccccccccccccccaaccccccccccccccccaacccccccaaaaaaaaaaciiinnnnttttxxxxxyyyyvvqqqmmmccccccccc -SbaaaacccccccaaaaaccccaaaaaccaaaaaaaaaaaccccccccccccccccaaacaacccccccccccccccccccccccaaaaaaaaachhhnnntttxxxEzzzzyyvvvqqqmmmccccccccc -abaaaacccccccaacaacccccaaaaaaaacaaaaaaaaaccccccccccccccccaaaaaccccccccccccccccccccccccaaaaaaacchhhnnntttxxxxxyyyyyyvvvqqmmmdddcccccc -abaaaacccccccccccccccccccaaaaaacaaaaaaaaaacccccccccccccaaaaaaccccccccaaaccccccccccccccaaaaaaccchhhnnntttxxxxywyyyyyyvvvqqmmmdddccccc -abaacccccccccccccccccccaaaaaaacccccaaaaaaacccccccccccccaaaaaaaacccccaaaacccccccccccccaaaaaaacaahhhmmmttttxxwwyyyyyyyvvvqqmmmdddccccc -abcccccccccccccccccccccaaaaaaacaaccaaacccccccccccccccccaacaaaaacccccaaaacccccccccccccaaacaaaaaahhhmmmmtsssswwyywwwwvvvvqqqmmdddccccc -abcccccccccccccccaaaccccaaaaaaaaaacaaccaaccccccccccccccccaaacaccccccaaaacccccccccccccccccaaaaacahhhmmmmmsssswwywwwwwvvrrqqmmdddccccc -abcccccccccccccaaaaaaccccaaaaaaaaaccaaaacccccccccccccccccaacccccccccccccccccccccccaaaccccaaaaaaahhhhhmmmmssswwwwwrrrrrrrrmmmmddccccc -abcccccccccccccaaaaaaccccaaaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaacccccaaaaachhhhhmmmmsswwwwrrrrrrrrrkkmdddccccc -abccccccccccccccaaaaaccccccaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaaccccaaaaacccchhggmmmssswwrrrrrkkkkkkkkdddacccc -abccaaaacccccccaaaaacccccccccaaaaaacaaaaacccccccccccccccccccccccccccccccccccccccaaaaaaccccaacaaaccccggggmmsssssrrlkkkkkkkkkdddaccccc -abccaaaacccccccaaaaacccccccccaaaaaaccccaacccccccccccccccccccccccccccccccccccccccaaaaaccccccccaaccccccgggmllssssrllkkkkkkkeeeddaccccc -abccaaaacccccccaaacccccccccccaaaaaacccccccccccccccccccaacccccccccccccccccccccccaaaaaacccccccccccccccccggllllssslllkkeeeeeeeeeaaacccc -abcccaaccccccccaaacaaaccccccaaaaaaaaaaacccccccccccccaaaaaacccccccccccccccccccccaaacaaacccccaacccccccccggglllllllllfeeeeeeeeaaaaacccc -abccccccccccaaaaaaaaaaccccccccccccaccaaaccacccccccccaaaaaaccccaaccaacccaaccccccaaaaaaacccccaaccccccccccggglllllllfffeeecccaaaaaacccc -abccccccccccaaaaaaaaacccccccccccccccaaaaaaaccccccccccaaaaaccccaaaaaacccaaaaaaccaaaaaacccaaaaaaaacccccccggggllllfffffccccccaacccccccc -abcccccccccccaaaaaaacccccccccccccccccaaaaaaccaacccccaaaaaccccccaaaaacccaaaaaacaaaaaaacccaaaaaaaaccccccccgggffffffffccccccccccccccccc -abccccccccccccaaaaaaacccccccccccccaaaaaaaaacaaaaccccaaaaacaaaaaaaaaacaaaaaaacaaaaaaaaaccccaaaacccccccccccggffffffacccccccccccccccaaa -abccccccccccccaaaaaaacaaccccccccccaaaaaaaaacaaaacccccaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaacccaaaaacccccccccccaffffaaaaccccccccccccccaaa -abccccccccccccaaacaaaaaacccccccccccaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaacccaaacaaaccaaaaaacccccccccccccccccaaaccccccccccccccaaa -abccccccccccccaaccaaaaaccccccccccccccaaaaaaaccccaaaaaaaaaaaaccccaacccccaaaaaacccaaaccccccaaccaacccccccccccccccccaaacccccccccccaaaaaa -abcccccccccccccccaaaaaaaaccccccccccccaacccacccccccaaaaaaaaaaccccaacccccaaccccccccaccccccccccccccccccccccccccccccccccccccccccccaaaaaa diff --git a/days/12/sample.txt b/days/12/sample.txt deleted file mode 100644 index 86e9cac..0000000 --- a/days/12/sample.txt +++ /dev/null @@ -1,5 +0,0 @@ -Sabqponm -abcryxxl -accszExk -acctuvwj -abdefghi diff --git a/days/2/day2.go b/days/2/day2.go deleted file mode 100644 index 5cde952..0000000 --- a/days/2/day2.go +++ /dev/null @@ -1,87 +0,0 @@ -package _2 - -import ( - _ "embed" - "fmt" - "strings" - - "github.com/ankon/adventofcode/2022/days" -) - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -type shape int - -const ( - Rock shape = 1 - Paper shape = 2 - Scissors shape = 3 -) - -type outcome int - -const ( - Lose outcome = 0 - Draw outcome = 3 - Win outcome = 6 -) - -var roundValueSimpleTheory = map[string]int{ - "A X": int(Draw) + int(Rock), - "A Y": int(Win) + int(Paper), - "A Z": int(Lose) + int(Scissors), - "B X": int(Lose) + int(Rock), - "B Y": int(Draw) + int(Paper), - "B Z": int(Win) + int(Scissors), - "C X": int(Win) + int(Rock), - "C Y": int(Lose) + int(Paper), - "C Z": int(Draw) + int(Scissors), -} - -var roundValueActualMeaning = map[string]int{ - "A X": int(Lose) + int(Scissors), - "A Y": int(Draw) + int(Rock), - "A Z": int(Win) + int(Paper), - "B X": int(Lose) + int(Rock), - "B Y": int(Draw) + int(Paper), - "B Z": int(Win) + int(Scissors), - "C X": int(Lose) + int(Paper), - "C Y": int(Draw) + int(Scissors), - "C Z": int(Win) + int(Rock), -} - -func simulateGame(rounds []string, roundValue map[string]int) (int, error) { - var score int - for _, round := range rounds { - if round == "" { - continue - } - - score += roundValue[round] - } - return score, nil -} - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - - rounds := strings.Split(input, "\n") - - assumedScore, err := simulateGame(rounds, roundValueSimpleTheory) - if err != nil { - return err - } - fmt.Printf("Score according to theory about guide: %d\n", assumedScore) - - actualScore, err := simulateGame(rounds, roundValueActualMeaning) - if err != nil { - return err - } - fmt.Printf("Score according to actual meaning of guide: %d\n", actualScore) - - return nil -} diff --git a/days/2/input.txt b/days/2/input.txt deleted file mode 100644 index 7507561..0000000 --- a/days/2/input.txt +++ /dev/null @@ -1,2500 +0,0 @@ -C X -C X -C X -A Z -C X -C Z -C X -B Y -C X -C X -C X -B Y -C X -B Z -C Z -C X -C X -C Z -C Z -B Y -C Z -C X -B Z -C X -C X -C X -B Y -C Z -B Z -C X -B Y -C Z -A Y -C X -B Y -A Y -C X -C Y -C X -C Z -C X -C X -A Y -C X -C X -B Y -B Y -C X -C X -B Y -C Z -B Y -B Y -C X -C X -C Y -B X -C X -C X -B X -C Y -B X -B Y -C X -C Z -B Y -B Y -B Y -B X -C Z -C X -B Y -C X -A Y -C Z -A Y -C Z -C X -C Z -B Y -B X -C X -B Z -C X -C Y -C X -C X -C Z -C Z -C Z -B Z -C Y -B Y -B Y -B Y -C X -B Y -C Z -C X -C X -C X -B Y -C Z -C X -C X -C X -C X -C X -B Z -C X -A Y -B X -C X -C X -C X -A Y -B Z -C X -C Z -C X -A Y -C X -B Y -C Z -C X -C Z -B Z -B Y -B Y -C Z -B Y -B Y -B X -B Y -B Y -C X -C Z -C X -C X -C X -C X -C X -C X -C X -C X -C Z -C Y -B Y -B Y -C Z -A X -C X -C Z -B Z -B Y -C Z -C X -C X -B Z -B Z -C X -C X -C X -B X -A Y -B X -C X -C Z -C X -C Z -B Y -C X -B Y -A Y -A Y -A Y -B Y -C X -C Y -B Y -A Y -C Z -A X -C X -C Z -C X -C X -C X -C Z -C X -B X -A X -C Z -C X -C X -C Y -C X -C Z -B Y -C X -C X -C X -C Z -C X -B X -C X -B Y -B X -C Y -C X -C X -C Y -C X -C X -C X -C X -B Y -C X -B X -B Y -C Y -C X -C X -B X -C X -C X -B Y -A Y -C Z -C X -B Y -C X -C X -C Z -C X -C X -A Z -C X -C Y -A Z -C Z -C Z -B Y -C X -B Y -C X -C X -C X -B Y -B Z -C X -C X -C X -B X -B Y -C X -A Y -B X -B X -B Y -B Z -C X -B X -C Z -C X -B Y -C X -A X -C Y -A Z -C X -A Z -B Z -C X -B X -B Y -A Y -B X -C X -B Y -B X -C Z -B Y -B X -A X -C Z -B Y -C X -C X -C X -A Y -B Y -C X -B Y -C Z -C X -C Z -B Z -B X -A Y -C X -B Y -C X -C X -C X -B Y -B Y -B Z -B Y -C Z -C X -C Z -C X -C Z -C X -C X -A Y -C Z -B Y -A Y -B Z -C X -C X -C X -C X -B Y -C X -C X -C X -C X -A Y -C X -C X -C X -C Z -C X -B Y -C X -C X -C Z -C X -C X -C X -B Y -B Z -B Y -C X -C X -C X -B Y -C X -B Y -C X -C X -C Z -C Y -C Z -C Z -C X -C X -C Z -A Y -C Z -C X -B Z -C X -C Z -C X -C X -B Y -B Z -B Z -A Y -B Z -C Z -C X -C Y -B Y -A Y -C X -A Y -A Z -B Z -A Y -C X -C Z -A Y -B Y -B Y -C X -C Z -B Y -C X -C X -B Y -C X -C Z -B Y -B X -C Z -C X -C Y -C X -C X -C X -C Y -C X -B Z -C Y -B Y -B Y -C X -A Y -C X -A Z -A Y -B X -C X -B Y -C X -B Y -B Y -C Z -C Z -A Y -C X -A Y -C Z -C X -C Z -C X -B Y -B X -C X -B X -C X -C X -B Y -C X -C X -C X -C Z -C Z -B Y -C Y -C X -C X -B Y -C X -C Z -C X -C Z -C X -C Y -C X -C Y -C Z -C X -B Y -C X -B X -B Y -C Z -B Y -B Z -B Z -C X -A X -C X -C Z -C Y -C X -B X -C Y -A Y -C Y -C X -B Y -B Y -C X -C Z -B X -A Y -C X -C X -C X -B Y -B Y -B Z -C Z -C Z -B X -C X -B Z -C X -B Y -B Y -C Z -C X -C Z -C X -C X -C X -C Z -C Z -C Z -C X -B Y -C X -C X -B Y -C X -C X -C X -A Y -C Z -B Z -B Z -C Z -C X -C Y -C X -A Y -C X -C X -C Z -C X -B Y -B Y -C X -C Z -C Y -B X -B Y -A Y -B Y -C X -C X -C Z -B Y -C X -C Y -C Y -A Z -B Y -C X -B X -A Y -B Y -B Y -C Z -A X -C X -A Y -C Z -C Z -B X -A Y -C Y -B Y -C X -A Y -B Y -C X -C X -A Y -B Y -C Z -C X -C Z -A X -A Z -C X -C Z -C X -C Y -C X -B Y -C Z -C X -B Y -C Z -C X -B Z -B X -C X -C X -B X -C X -C Z -C X -C X -C X -C Y -B X -C X -C X -B Y -B Y -C X -B Y -C X -C Z -C X -B Y -B Y -B Y -C Z -C X -A Z -A Y -C X -C Z -C Z -A Z -B Y -A Z -C Z -B Z -B Y -C X -B Y -C X -B Y -A Y -C X -C X -C X -C X -B Y -A Z -B X -C X -C X -C X -C Z -B Y -C X -B Y -B Y -B Y -C X -C Y -B Z -C X -B Y -B X -C X -C X -B Y -C X -B X -C X -C X -A Z -C X -A Z -C X -C X -C Z -C X -B Y -C Z -B Y -C X -B Y -C Z -B X -C X -A Y -C Y -C X -C X -B Y -B Y -C X -C Z -C Z -C Z -C X -C X -B Z -B Z -A Z -B Y -B Y -B Y -A X -C X -B X -B X -C X -C X -C X -C X -B X -B X -B Y -B Y -B Y -B X -C X -C Z -B Y -B Y -A Y -A Y -C X -C X -C X -B X -C Z -C X -C X -B Y -C X -C X -C X -C X -B X -B X -A Y -B Z -C Z -B Z -A X -C X -B X -C X -B Z -C Z -B X -B Y -C Z -C Y -C X -C X -C Z -C X -C X -C X -C Z -C X -B Y -C X -C X -C X -A Z -C Z -C X -C X -C X -C Y -A Y -C Z -B X -B X -C X -C X -C Z -A Y -C Z -C X -B Y -B Y -B Z -B Y -C X -B X -C X -C X -B Y -C Y -C Z -C X -C Z -B Y -C Y -B Y -B X -C Y -B X -C X -C X -B Z -C Y -B Y -B Y -B Z -C Y -B X -B Y -C Z -A Y -B Y -B Y -A Z -C X -C Z -B Z -C X -C X -B Y -C X -C X -B X -C X -C Z -C Z -B Y -B X -B Z -B Z -B X -C X -C X -C X -C X -B Y -A Y -B X -C X -C X -C X -B Y -C Z -B X -C Y -C Z -B Z -C X -C X -B Y -C Z -B Y -C X -C X -B Y -B X -C X -C X -C X -C X -B Y -A Y -C Y -C X -C X -B Y -B X -B Y -C X -C X -C Z -C X -C Z -A Y -C X -C Z -B Y -C Z -B X -A X -C X -C Z -C Y -B Y -C X -C Z -C Z -B X -C X -C X -C Z -C X -A Y -B Y -C X -C X -C X -C X -C X -C X -B X -B X -C Z -B Y -C X -C X -A Z -C X -C Z -B Y -C Z -C Y -C X -C Y -C X -C X -C Z -B Y -B Y -B Z -B Y -C Z -C X -C Z -B Y -C Z -C X -C X -C X -C Y -C X -C X -B X -C X -B Y -B X -B X -B Y -B Y -B Z -C Z -A Y -B X -B Y -C Z -C Y -C X -C X -C Z -A Y -C X -C Z -C X -B X -B Z -C Z -B Y -C X -C X -C Z -B X -B Y -C Z -B Z -B Z -C X -C X -C X -B Y -C X -C Z -C X -C X -B Y -C X -B Y -B Y -C X -C X -C X -B Y -B Z -C X -C X -B X -B Y -C X -C Y -B Y -A Y -C X -C X -C X -C Y -C X -C Z -A Y -B X -C Z -C X -C X -C X -B Y -B Y -C Z -C Z -C Y -C Z -C X -B Y -B Y -C X -B Y -C X -B Y -C X -C X -C X -C X -C Z -B Y -B Z -C X -C X -B Y -C X -B Y -C X -B Y -C Y -B Y -C X -B Y -C X -B Y -C X -B Z -C X -B X -B X -B Y -B X -B Z -C X -B Y -C X -B Z -B Y -C X -C Y -C Z -A Z -C X -C X -B Y -A X -C X -B Z -C Z -B X -C X -C X -B Y -B Z -A Z -A Z -C X -C X -C X -C X -A Y -B Y -B Y -C X -B Z -C Z -C X -C X -B Z -C Z -B Y -C Z -C Y -C Z -B Y -C Z -B Z -B Y -C X -C Z -C X -C X -C Y -C X -B X -A X -B X -C X -C Z -C Z -C Z -B Y -B X -C X -B Y -C X -C X -C X -A Y -C Z -A Y -C X -C X -C X -B Z -C X -C Z -C X -B Y -B Y -B X -C X -C Z -C Z -A Z -B Y -C Y -B Y -C Z -C X -A Z -C X -B X -B Z -C X -B Y -C Y -C X -B X -C Z -C Z -C Z -C X -C X -C X -A Y -C Z -B X -B X -B Y -B X -A Y -C X -B Y -C X -C X -C X -B X -A X -B Y -C X -C Z -B X -A X -C X -B Y -C X -C Z -A X -C X -B Z -C X -C Z -C Z -B Z -C Z -C X -B Y -C X -B Y -C Y -B Y -C Y -B Y -C X -B X -C Y -C X -C X -B Y -C Y -A Z -C X -C X -C X -C X -B Y -B Y -C X -C Z -C X -C X -C X -B Y -B Y -B Y -C X -B Y -B X -C Y -B Y -C X -C X -B Y -C X -C Y -C X -B Y -C X -B Y -C Z -C X -C X -C Z -C Z -B Z -C Z -C X -C X -C Z -C Z -B X -C Y -C Y -C X -C X -B Z -C Z -B Y -B Y -C Z -C X -C X -B Y -C X -C X -C Z -C X -C Z -A Z -B Y -C Z -C X -A X -A Z -B Y -B Y -B Y -B Y -C Z -B X -C X -B Y -B Y -C X -B Y -B Y -C Z -C X -B Y -C Y -C X -C Z -C X -A Y -C X -C X -C Z -A X -B Y -B Y -B Z -B Y -C Z -C X -C X -B Y -C X -C Z -C Z -C X -B X -C Z -C Z -B Y -B Y -C X -B Y -B X -C X -A Y -B Y -B Y -C X -C Z -B X -C X -C Z -A Z -B Y -C X -C Z -C X -C X -C X -B Y -B X -B Y -B X -C X -C X -C Z -C X -C X -C X -C X -B Y -C X -B Y -C Z -B X -C Z -C X -B Z -C X -A Y -C X -C X -C X -C X -C X -C X -B Y -C X -C X -B Y -C Z -C Z -B X -C X -A X -C X -C X -B X -C Z -B Y -B X -C X -C X -B Y -C Z -C Y -B Y -C Y -B X -C X -B Y -C X -C Z -C Z -B Y -B Y -A Z -B X -C X -C X -C Z -C X -C X -B X -C Z -A Y -C Z -C X -C Z -C X -C Z -C Z -A Z -A Y -A Y -C Z -C X -A X -C X -B Y -B Y -C X -C Z -B X -B Z -C X -C Z -B Y -C Z -B Y -C Z -B Z -B Y -C X -C X -B Y -C X -C X -C Z -B X -C Z -C Z -B Y -A Z -C X -B Y -C X -C Z -C X -C X -B Y -C Z -A Z -C X -C X -B X -C X -C X -B Z -B Y -B Y -B X -C Y -C X -B Y -B Y -C X -C X -C X -A Z -C Z -A Y -C X -B Y -B Y -C X -C Z -C X -C X -B X -B Y -C Z -B Z -C Y -C X -C X -B Z -B X -C Z -C X -C X -C X -C X -C X -C X -C X -C X -B Y -C Y -C X -B Y -B Y -B Y -C X -C X -B X -C Y -B Y -C X -B Z -C X -C X -B Z -C Z -B X -B Z -C Z -B Z -C X -B Y -C X -C Y -A Y -B X -B Y -B Z -C X -B Z -A Y -C Z -C Z -C Y -B Y -B Y -B Z -C X -C X -A Y -C Z -C X -C X -C X -C Z -C X -C X -C X -C X -A Y -C X -C Z -C Z -C X -B Z -C X -C X -A Y -B Z -C Y -A X -C X -C X -C Z -C X -C X -C X -A Y -A Y -C Z -B Z -B X -C X -C X -C X -A Z -B Y -C Z -C Z -C X -C X -C Z -C X -B Y -B X -C Z -C X -B Y -B Z -C X -C X -B Y -C Z -C Z -C X -B Y -C X -C X -B Y -A Z -B X -C X -C X -C X -B Y -C X -C Z -B Y -B X -C Z -B Y -B X -C X -C X -A Y -C Z -C X -C X -C Z -B Z -B Y -B Y -B Z -C X -A Y -B X -C X -C X -B Y -C X -C Z -B Y -C X -C X -C X -C Y -B Y -B X -B Y -C X -C X -C Z -C Z -A Y -C X -C Y -B Y -B Y -B X -C X -C X -B X -C X -C X -C X -B X -C X -C Z -C X -A X -B Y -C Z -B Y -C Z -C X -C Z -C X -B Y -C X -B X -A X -A Z -C X -C Z -C X -C X -B Y -B X -B X -B Y -B Z -C Z -C X -C Z -B X -C X -B Y -B X -B Y -B Y -C Y -C X -B X -B Y -C X -C Z -C X -B Y -C X -C X -B Y -C X -C X -C Z -C X -B Z -A X -C X -C X -B X -C Y -C X -B Y -C X -C X -A Y -A X -C X -B Z -C X -A X -C X -C Y -C X -C X -C X -C Y -C X -C X -B Z -C X -C X -B X -B X -C X -C X -B Z -C X -A Y -B X -B Y -C X -C X -B X -B Y -C Z -B X -B Y -C X -C X -C X -C Z -C X -C X -C X -A Y -A Z -C Z -A Y -B Y -B Y -C Y -C X -C Y -C X -B Y -C X -C Z -A Y -B X -C Z -B Z -C Z -A Z -A X -B Y -B Y -C X -C Y -B Y -B Y -B Y -C Y -C X -B Y -B Y -C X -C X -B Y -C X -B Y -B Y -C Y -C Y -A Y -B Y -B Y -C X -B X -B X -C X -B Y -A X -C Z -C Z -C X -A X -B Y -C Y -B Y -C Z -C Z -B Y -B X -B Y -B X -B X -C Y -C Y -B Z -B Y -C X -C X -C Y -C X -C X -C X -C Z -B Y -B Y -C X -C X -C Z -B Y -A Y -B Y -B Y -B X -C X -C Z -C X -C Z -C X -B Z -C Z -C X -B Y -A Y -C X -A Y -B Y -C Y -A X -C X -B Z -C X -B Y -A Z -C X -C Z -C Z -C X -A Y -C Z -C X -C X -B Y -C Z -B Z -B Y -B Y -C Z -A Y -C X -B X -C Z -C X -B Y -A Y -B Y -B Y -C X -C Y -B Z -B Y -B X -C Z -C X -C X -B Y -A Y -B Y -C X -C X -B Y -B Y -C X -C Z -C X -B Y -C X -B Y -B Y -C X -C Z -A Z -B X -C Z -B X -C X -C Z -B Y -B Z -C X -B Y -C Z -C X -C X -C X -B Z -C X -C Z -C X -C X -B Y -B Y -C X -A X -A X -C X -C X -B X -C X -C Z -B Y -C Z -C Z -C X -A Y -A Z -C X -C X -B Y -B Y -B Y -C Z -B Y -C X -C X -C X -B X -B Y -B X -B Y -A Y -C X -B X -C X -C Y -C Z -C Y -C Z -C X -A Y -C X -B Y -C Z -C Z -C X -B Y -B Y -B Y -C X -A X -C X -B X -C Y -C X -B Y -C Z -C X -C Z -C Z -C Z -A Y -B Y -B Y -C X -A Y -C Y -B Y -C X -B Z -B Y -C X -B Y -C Z -B Y -C Z -C X -B Z -C Z -C Z -B X -C X -C Y -B X -B Y -C X -A X -B Y -C Z -B Y -C X -C X -B X -C X -B Y -C X -B Y -C Z -C Z -C X -C X -A Y -B Y -C Y -B Y -B Y -B Y -C X -C Y -A X -A Y -C X -C X -B X -B Y -C X -C Z -C X -B Y -C X -C Y -B Z -B X -C X -A Y -C X -C Y -C Z -B X -C X -C Z -C Y -C X -C Z -C X -C Z -B Y -B Z -C X -A Y -C X -C X -B X -B Y -C X -C X -B Y -C X -B Z -C X -C X -C X -B Z -A Y -B X -B Y -B Y -B Y -B Y -C X -C Z -B Z -C Z -C X -B Y -C X -B Y -A Y -C Y -B X -B Z -C X -C X -C X -A Y -B X -B Z -C X -C Z -B Y -C Z -C X -B Y -B Z -C Y -C Y -C X -C X -B Z -B Y -A Y -C Z -B Y -B Y -A Z -C X -B Y -A Y -C X -C Z -B Y -C X -A Z -C X -B Z -B Y -C Z -B Y -C X -B X -B Y -C X -B Y -C X -C Y -B Y -B X -C X -C Y -C X -B Y -C Y -C X -C X -B Y -B Y -B X -C X -B X -A Y -C X -B Y -C Y -C Z -C X -B Z -B X -C X -C X -C Z -C Z -B Y -C X -C X -B Y -C X -C X -A Y -C Z -C X -A X -B Y -C X -C X -C X -C Z -B Y -C X -B Y -B Z -C X -C X -B Y -A Z -C X -C X -C X -A Y -B Y -C X -C Y -C Z -A X -C X -C X -B X -B Y -C X -B Y -B X -B X -C X -C Z -B Y -B Y -C Z -B Y -A Y -C X -B Y -C X -C Z -C X -C Z -A Y -C X -B Z -C Z -B Z -C Z -C X -B Y -A Z -C X -C Z -B Y -B Y -C X -C Z -A X -B X -B Y -C X -C X -B Z -C X -C X -C Z -A Y -C X -A X -C X -C X -B X -C Z -B Y -B Y -C Z -B Y -B Y -C X -C X -B Z -B Y -B Y -C X -A X -C X -B Y -C X -B Y -C Z -A Z -C X -C Z -C Y -B Y -C X -C Z -C Z -B Y -B Z -B X -C Z -C Z -B Z -B Z -B Y -C X -B Y -B Y -B X -B Y -C X -C Z -C Z -B Y -B Y -B Z -C X -C Z -C Z -C Z -C X -C X -B Y -C X -B Y -B Y -C Y -C X -B Y -C X -C X -C X -C Z -A Z -C X -A X -A Y -B Y -C X -B Y -B Y -C Y -C X -C X -C X -B Y -C X -A Y -B Y -C Z -C Z -C X -A Y -C X -B Y -C X -C Z -C Z -C Y -B Y -C X -B Y -B Y -C Y -C X -B X -C Z -C X -C X -C X -B Y -B Z -C Z -C X -C Z -B Y -A Z -C X -C Z -B Z -A Z -B Y -B Y -C X -C Z -C X -C X -C X -C X -C Z -C X -B Y -C Y -B Y -C X -C Z -B Z -B X -C Y -C X -B Y -C X -B X -C X -C X -C Z -C X -B Y -C X -C Z -C Z -B X -C X -B Y -C X -B Y -B X -C X -A Y -C X -C X -C Z -B Y -C X -B Z -C X -C X -C X -C X -B Z -C X -B Y -C X -B X -C Z -C X -B Y -C X -C X -C X -A Y -B Z -C Z -A Z -C X -B X -C Z -C Y -B Z -C X -B Y -B Z -C X -C Z -B X -C X -C Z -C X -B Y -B X -B Y -B Y -C Y -C Y -C Y -C X -B Y -B Y -C X -C X -C Y -B Y -C X -C X -C Z -C X -B X -C X -C Y -C X -C X -C X -C Z -C Z -C Y -C Z -C Z -B X -C X -C X -B Y -C X -C X -C Z -B Y -C X -C X -C X -A Y -A X -C Z -C Z -C X -C X -B X -B Y -C X -C Y -B Y -B Y -C X -C Z -C X -C Z -B X -C X -C X -B Y -B Y -B Y -C X -C X -C X -C Z -C X -C X -B Z -C X -C Y -C X -A Y -C X -C X -B X -C X -C X -B Z -C X -C X -C Z -C Z -C X -C Y -C X -C X -C X -C X -B Y -C X -C Y -C Z -C X -C X -C X -C X -B Y -B X -C X -C X -C Y -C X -B Y -C X -C X -C Z -C Z -C X diff --git a/days/2/sample.txt b/days/2/sample.txt deleted file mode 100644 index db60e36..0000000 --- a/days/2/sample.txt +++ /dev/null @@ -1,3 +0,0 @@ -A Y -B X -C Z diff --git a/days/3/day3.go b/days/3/day3.go deleted file mode 100644 index 9cf48ce..0000000 --- a/days/3/day3.go +++ /dev/null @@ -1,96 +0,0 @@ -package _3 - -import ( - _ "embed" - "fmt" - "strings" - - "github.com/ankon/adventofcode/2022/days" - "golang.org/x/exp/slices" -) - -func findCommonItem(compartment1, compartment2 []byte) (byte, error) { - for _, c := range compartment2 { - if slices.Contains(compartment1, c) { - return c, nil - } - } - return 0, fmt.Errorf("no common item") -} - -func getPriority(item byte) int { - if item >= 'A' && item <= 'Z' { - return int(item - 'A') + 27 - } else { - return int(item - 'a') + 1 - } -} - -func calculateMispackedItemInCompartmentsPrioritySum(rucksacks []string) (int, error) { - sum := 0 - for _, rucksack := range rucksacks { - if len(rucksack) == 0 { - continue - } - - l := len(rucksack) - compartment1, compartment2 := rucksack[0:l/2], rucksack[l/2:] - commonItem, err := findCommonItem([]byte(compartment1), []byte(compartment2)) - if err != nil { - return 0, fmt.Errorf("cannot find common item for %q: %w", rucksack, err) - } - sum += getPriority(commonItem) - } - return sum, nil -} - -func commonItemTypes(list1, list2 []byte) []byte { - result := []byte{} - for _, c := range list2 { - if slices.Contains(result, c) { - continue - } - if slices.Contains(list1, c) { - result = append(result, c) - } - } - return result -} - -func calculateGroupBadgeItemPrioritySum(rucksacks []string) (int, error) { - sum := 0 - for i := 0; i + 3 < len(rucksacks); i += 3 { - common1 := commonItemTypes([]byte(rucksacks[i]), []byte(rucksacks[i+1])) - common := commonItemTypes(common1, []byte(rucksacks[i+2])) - if len(common) != 1 { - return 0, fmt.Errorf("expected only one common item, but got %q", common) - } - sum += getPriority(common[0]) - } - return sum, nil -} - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - - rucksacks := strings.Split(input, "\n") - prioritySum, err := calculateMispackedItemInCompartmentsPrioritySum(rucksacks) - if err != nil { - return err - } - fmt.Printf("Sum of priorities: %d\n", prioritySum) - - groupBadgePrioritySym, err := calculateGroupBadgeItemPrioritySum(rucksacks) - if err != nil { - return err - } - fmt.Printf("Group badge priority sum: %d\n", groupBadgePrioritySym) - - return nil -} diff --git a/days/3/input.txt b/days/3/input.txt deleted file mode 100644 index cd857ef..0000000 --- a/days/3/input.txt +++ /dev/null @@ -1,300 +0,0 @@ -jNNBMTNzvTqhQLhQLMQL -VCwnVRCGHHJTdsLtrdhrGdsq -wFJZTbRcnJCbpwpFccZCBfBvPzfpgfgzzWvjSzNP -wDWgDfWNTvwvgFfWfddGldJVprrrVdNlrN -nLnmLSnmMVJvSrHqdV -MsmsbLvtzMjFsCPDsfBwwT -WTqSCqWSWqSgVZqJHpHmHrhMMVrRhBnn -PtLGLGddGGMCpprM -jFvLPPlLjvfjjffsclvPqzzJWTbqNSWZsbSTDzCW -lLSSrfmddlNpnmLdfSPddDdbZQTZgZjbZgjcQZHQPjQgZP -MJMnhzBJVJwvGsMRhRhTsHTjZjHFctbtHZcgZj -vzvBWGJMVGwWGGhGqVBnGzVGDfCDmrqNfrrLSdpSfLSpNmNC -qGWLgfbWhqpLgZbJvTRWJTvMWRslMv -FQwPwNPCVFQQdNcFHNcwwsvslRDRTMDMsVTGJGtRTs -wQHnwnQFPNPdjnnPjhphGqBrfpBBBfZf -mpVpmtPhVtPBLLbQTJpBLZ -vzFMlMzvvRZMTbJQJQbf -srqzvRRqdvzFFrDnvqldFVtwCVCHWNqJHNNcHchCPt -CQJJLZCJLqNMMDDgGLVV -RfRFFszTtzbWTFnRtFrRrWvNHghvBVGgMffvmBVDNgGV -znsjWzstnWjbDnDbTZCpwZcjpjZqQCwSPp -jRrzzrPjLnnpQQDsjj -CTVnTlZWHTcqZBcTTTHqWscQsQDQQDsmmQfvfhwDmv -qlWFWWHTZTlqTFWZHtBVFdlTGdNzRnNngbbSrrSNNzPgPGSz -cWjbcjnssMmRPWbGsWcMbfLBFrZBBLLgZwBrlfLQZtCw -vqpvFHNvhvJzdZQZtlgNNwlrrw -JzqVVVVpzhVJqzhSzJhhDVnFjRRMsPnSRcGMRMjWjWmR -NznNGQgSRQffbbsR -jjjCLwdvLcrhqdblFJsFSPfbDP -qrrvwHqjtLmSSggpBtgn -LGPtFtTfTfTfLrrWTSWGPrrsszbsjZHzgdzSwzbHdsglwl -NhHpVpqNNqbdszRRRb -ccBMJVDNCvvhDNpvNDpnNCVCHFPTmfLTGPMQrfLGmMLWWQQL -dRgRhVLRlncZSSrtLp -WJmwvvvjQvWwFBBvFJPHpwvGWTScGsrZtttGTSsrzTsSZt -FFHJjmjjjPMvfHfwpdRqMppghdRCddDg -NDTRFSnNsVVBDVlM -JjLZWqwjHvfrvmHHvjLWWLlhPlnPlChlQhJQnnzPPBCV -mwHvHmpvwpLmjnvpvLvvNGcTTggRbdTGcbNbTTpS -GGhZQMsmGRfMwfpclgdBlbblBBZgJc -tFvFSTSDnDTTLtcFMbWcBgclJrgd -vzDtzMVtnLTTMTSjSDHtppqhsqqfGjmpPhmsRGPG -MfJtWTTMJfzBbVWPZWQbNnDV -FvlgSHSLvmCvZjgcCQQsPQQsjnbVDNVsdn -HLhclRlHRmHvmLmclLZFSFwRRRpJMtwJwfGGrrtrwfpf -scsswLQcGmQmNHCqvrsHqfff -bdnPSMMMClbBBPCdDDnDVMDWWWvfvWFfFJfNqqNVFqFNfr -bDPTlSTPPbSPjnPSbGmQLCcjLjwzRLcmCG -tFFJjMnFhdcMMJlWtdnlFczBSZGNSjGGbBGZLbZZbLGB -QRgqwwvsLssZnGCz -gqfvvnpfHwRmHTFdFcPdJJmJJc -fccTzVVcfSmdThTTFJPFgg -wLsWfppsjBrnnwjCBZnZqJJQGhBdFJddQhFqdQBG -pZrNCWLwLZLjwwWMftmNzttDcVzVvt -rZnVVjVSMcrwsNbc -dLvQLBLFddvBLzpGmddQCqNswzsMjbhgbblbcwshlb -LLCCWjGBFPmCWdmmPWLdWBpLRZDSPRnHSStRfnZnZTnSSTfJ -ddfnQRbpldRlRLgFglqGCLqsGq -BWBVDZWTBTDPvVTZVDBDNMbhcLLHsFqgvHJsLCJCGcHGsJLH -NPZPDMWZMbZrBVMDDWNmBhMVpSSRpzjjfjpwRnSpwzRzdzjr -bvPSBttgGmZwScwShS -NJspjJLdprzHgjrLzLNrnHQCmmcZQWlcQcNQwlwcQCZC -HdRJsJrdHTbqGMDtgDqT -sNVvSdTstDCtdzdzSCwTzCRhRQjfclMflppjGhffjZcN -rgWlrnLLbqbQMfMphpWjjf -BmrnrFPnnBLlqVwDCtCtVPDTzT -mJMqlVlttQlFVmzFQMQMbQMSSDNwwdSddNddwdDswRDVdR -GGZgcfjrvCCZvgCZqvPHSwRBBsBwswcwBNTDTcSR -GZppfGHGrgGprZhLthFJhFqLWWFhtq -WDHHLtRBHgDnVrWFVFBTdzzZLLjZzjjvddLsvv -JlqmMpCMCGMwbwZddTtCtv -cJJqSplpfSGccJGthFVcVHgFBWBgHgDB -tlFwbWtQFLJhlBFlWPbwmsQndTrrqdnggjqdgnTgTT -GCMBDDCvRpDVpRpHrsgdqTjqgdHcsjHd -MDDvCVGzBGfpzBSNMSRRmwbLWlPmzbPmlJlWbFbJ -fzFzFHBfnvpHFbnzbHfBHZggCGgtZCltDGggdCCVtZVD -sLMNSccQLMSrmLcshLvtCGllPtDdGgtJgmlV -cwLMwwNhQhsWSjqTqHnHbjWTvH -NWlqqhNNnGtNvvWQdrVGBBQdVrwRQr -mppCjppMrDTSgDppCDTMQVRwdBbBQVVbQdQsVB -pgzzTFFFrjHqHnqJFWnh -ncQrhQjqjVQhGsGBbhtsstTp -RllWFLRfZrGlBTbg -vFLLmfNRFSNDfSNjcwqJVrVVzQjc -mmGrgwmGDGcVWVjNNW -nDsqfPCHnpntDssfJPDPjWWhjNTTcjjhTTNcqWcc -DfPCJLpbldRrlrdwmw -dJDNbRhNbJdhqCnrWjhsTWvplg -LMHrttLFcMmcMFLmtGplCggpjjnvTpgnTTFT -czZMzrzVZzHZdNdbDDqDVQNR -sbsJgbsmzdgRgWdg -LLLFBzGMLjzzFtVFwwwCPPRCCqQQTnnCMMCMCC -GllfptwjLjlGFVFjGzpFFNbJDmprrNDsDmDvJhmcvp -SccPbfbncpcfsjbRjMBCTTFGMTCQtJtzFFFJ -vvvdgVhlmlwlgZLgmJhWQCWGGbWtWJhzTJ -NbLNDdbLVmqqmfcsrHcrpPqrcH -HcgDBJSHTCzjjnMNJjrW -VppGMwFwllwwbZZrjvnqmzmnzpqjNv -wZlhtPGPLFVFlGZbVtVTQLLBQRRTSHTSMDCgLs -HPMMnhBHlMnMBPBHJHPWfdnBmjvLZvjTvZTZDgTgTmQmZhZZ -SrzrSScrctrwVzCSCmzQjmLTLvGDvTjGbm -CswstFRNpcwVNRrVVSVwpwpHJnnWWBBHfWHlffWfQMnM -mlFMtqjvMdqjmMCCJZsRQBnszlZz -HcNgcPLcHLwtcfZBTsnsHJBJTzCQ -LGGNhbNtNLDfcgcwfbgthfwFrqqVdFMqMMhMmvShFqmvVv -NbvbBGNvhNhnhpbgpGfBvNgmRjCdPCPCCRCQmmpRdTmTPR -qqFSSqWrtSSccjMdQMHFMBjPMj -SBDSBZZZwGGZNJJg -qTdHSLSFRZRHHZVgpzhbJszchsnsLg -tDvflvrGttDCjlQfmCGvtCftczhbzwJczcJgznNmzJNhwgsp -tQlDCDtrfrtlGrjlQBHFHPVHbBbZqTZdVZBF -MTwvsQJMvvHwVMMJMQNNJRPWWjCllrlWGFlSFCpjgFVSWr -zhcmnRZmqmWjCSFrFqCW -ZbmhZcdZznZfndtwDtMMsRQTTQNRQw -ZhhVqQTvZvVhSmQZcClRCLPCgTGGLbgl -dJWHwndMHswswlGbCmclmLHbbP -dnwwNJnjBjwwdddnjndfWvmvSNZQNrVVmZvZFvvQQv -trlrlrZzsjRjdFhlpwdpnpdp -QqLvvLQmLfQTLbLTfHmqHHLqQgFBdCJBBgggCJdhgJwCggBF -DPDvqLqffqfhSVjVPSPtsj -gsnVdcBcjMMntGMh -RQZLRZlZDRJDCzCjblJSDjQZWWTWPCThMTFGNPTNttGwCFMh -pDlQbSlzpQsjVpjHVfgs -zgqtCtJltdGttJgVGPPJCtJvQFsFFbTFssNDNDsHLbTQbssP -rRcwBnnpcmBqpbLHDspTbFsb -mwRqrqrmWrZnfWmBmnRZlgClgJCJlGJzClGMtG -jlzHllmPnpHlHZBWZJJDWMBNVH -bQrhDbcLgsQrtdVCJWfCCBMMVWrJ -QhGdGcLGwwwtcDzznppPpPwlpnSS -qbpqvWFHbFHHsWwPqPpsVWZTlDcLDddddDrmrcVZDrmT -MCgSSJMCztdmcLzlrlDl -QCRMRSnNtRSqqRjsjLPPvp -ZnZrTfsWWvhVSRmzqqnn -pLGBLBgLCpgGpbdLbgMClJTmmhShSRShqSBDQSRRmQVV -dpJPldgMMbglFdrNWWjHZNccTjZP -CCZCQzwwdmMGDWMmhCMJgpnrnwsTrFNLgnpNgg -jfStHtcjqDPbPtvqvgLNpppnHsrsFgnFNp -fcqqPPPtPSfRVBBRPRPbvQzzhQWGZQVQQZDQMMzGQM -VVlDNDgppgtNltlrJPbjSzPPzjsMsjBBMWMM -LmGRmfmwCqQqbsQBMqJj -cHRcCFfmfmGLJLGFcJLFwfdlhDgptthhHpVrNVdhlvhl -vSSdnBVpscwZcBZB -mLHzqtGtNfGHHFNHMhJMthsbcJtctZTw -GHqHHGzNDNFCfqllCFqVDdPSDQnddvcpPQjdjg -CMWcwGTrvzDWzrDccDCGzTTTplZgSjggjSpSljSjBpSmgmWB -nssRttdsnhsdbFhtVFhNpgwNpBBgHHBBBBZSjNSl -PnVPVPLFtvPvTwwrQq -tlQlqlJCCJWgFrprPjpGVpQzvp -SDbwShHbBZZbhcBdDBDSTrsVpPrzzzHVzNllzGlVNv -BTbbScwRhwZLnLtfJFLFJgWl -VDfPVHfDVMMfHSPSMTVfqgFthFcFrtcdhrhDQdDmdcdt -bWGGHCplWnJNpJCCnlnNwdcwQhmmdmtwddBNcc -HpGCnZGllzlzJWjnCbbnCnRvfvsSTVVSgVLqSsLsLzPPLV -fQqcfqfSDzDWffDZ -NcCLCtPCPMtNBwdthpLhPwzsHrszsZssTsWrDrDVTNNH -twMPBtCpLBCtwMPpJcMBSjjnngqSjQQJbQjjmgmn -vQwVQQVqcJvVJvCpQBCLpdgSFCdjjWWnMSgnSjgjbj -hszPRDTVDWWWRnjWWj -TtDDZsszlPllhPzmPVGssTPpQLcpvpBpZpcfpvrvQvBQLv -sRmGqqzzzgCtRrttCP -cffSwNDddTdfGWtgNCrtGMPP -GGcTwHwHvjqLLjLvlJ -JSdjLJMBdMSrfwwLpWgzWmvDhggzWvfmgD -VsRtVllstHHNllsQsHQRzchcnDmvmvnRvvvcnZ -tGVGCTTTtTFVbsTTNTHsTTqBqBLrBCjqBwqJwqBzLqzw -MhjTJjlSDrplQvFQ -RHttqbNGGmbbLmLmdqbgnFQwrZswQrwDpFpppdwfvQ -gCNmDHHRCLHnWWSCjhWPShPz -BvzpbBwBmsDrmGVgZFDm -TnNRdtlRlCdFFGTLffrrGf -jltNtRCPSlPNtcpwpGzjMBpvbhps -hflJphNDmmbpfnfplbcvLsHVLsrsZsVvCb -FgTFWqTBfFPfFqQqTwHsHccVVLQCZZZCVH -BSSRTGWBgFggBWgBGStTGpzNztmjjzhhzDfNnMjnph -mDDFjjFmVlTZJttffD -hhRvNNCvdNMRLzhSzpptwslNTfNQntsJQZZTlN -WCdMzdMzhMdvRvLhCRLPvjgHmggmbmbblgWcGmcbcG -cScMdhsDhDDdvGzZptzGcnGtpB -NPWjJqrjJWwrSFWRJlrlNWJLtZznLBBzZznLqnpqnpnznV -NWNQwNPjCSQTQhTd -fVVCVccppZMZMMCBzJTNJHWZTWZzNF -QrmmPhDqPhsPRhrlbgRDbbPDJNJTnJzmzzfNNTNHNJNWmnvF -DgbPLbPsQsrbsqLbgllsQQptfwSjwtVLfwdcpCjVwwSp -ZlsmlrZZJcQmhBhlNrsrJRRbRCRggRbzGCRHgRCDGB -fMFvdfVTTdjWTTTfvSjVjpjzcCbFHGPHPDbPHRCFGGRHHG -cdvfSWjfjpdVqSwSvMdLrlrmhqZhhrrLLJQhNr -sWVVmDJsNWNjcSNJZcNcZWWsHTGHTChhHGtHsFFbbsfHhH -nqPRwQRgpQRPQQgMQgQLQqBhvTRtfdfvfCbFtTFFFTtvff -qgrPMLLPpVlbDrVrWD -VcGjcCHcVHPrGnjQDQgDgQDFtdglRtlQ -bWWhfzJhvZWJzNpmRTtsDLDgRTsNddFT -MhJMhJbMmSZbJZwSCtjqcGrrnGjC -FCvpgDsZNsCbvvvpVwcDrjcrmVMwVwHJ -fhfWdPhhhhRQQqzdLSRHRHJjBTTmcrTMrMrwmczcwwTz -qndhdQWndftfhWStfLQQfWgFNsgFpHCtgCNbGZZlZCll -mqTCNhTNmGTLwLNfLrSrgZHDvfPDPv -cjsMQppsFnFslnRQQGMDHGZHSgzHPDZDSf -stWFjcFFsJlQcQtwtbVwCmCthmBTGb -fmsffcqhmqPsnTCnCcQpzjSSNpBWBTQpVSSD -vHbgLRvvvzdgjVVjWg -WltLWvWlqcChrhlf -CtwjffWrdznRtzCwLsmGLlLMsMmMGb -cZFFbgPgJZDchMMPVsmlPGmG -SpNFJBJccNgDcTJJTdbStbnntrCdSrjWnb -qWzgNFqzqHNTBzFNCZCGPpPlHmdPblls -rfSJRJnhhnJDjrfvRStCmpdGsdlDpZZZPbPCmW -cffRvfnnVRjFTWVTLQMFWN -VcHhVrVCQQWhffzcRZznnZFf -dDSCGSsSblwDdmLqvnFZzNZplfpfRZfBnl -tCCwGmSqbqtwsVPjVJWtJHHhQV -fvvTcWzGcCJrJGJvvHMbZTmRQTbpMdQQsR -SgFhVgllLgjLgwlwljFqVFSFdjmBHmZdRMdZpbjpmpjBsHdM -LNqFnlDgVqllwLFLnVSgLFZtCzzzzvCGGccCCDCfvJrv -FczpzmSjVVpSQrzzcRpRcrwqMtJqwtvtLHvQwtLtnJMw -TvbGGbNfGCBBLHtJBHDZDMqD -shgdNTGgvNsflspcPjzVdmppczrV -JHLPLTsSllgSSPPSPLTRTdjCZGZDGGgCdqZtZCZdZt -mhFpnpFwqdGbdFDt -prpWcvnmhmpccBBJMJJlPWLHMDSDWW -GcMcjDbDMMjqHBHVlHvv -rLCrwNJCnwrZNLWQQwzQpRqQPlBRVVBRvvtHqf -zhnrnzdrCwLJCwzwCMGcbdFTscTmgcFlgc -cnwlFrdMsggblgsrMbncwrsWzjGBTjznBzWNzPzTzfjTzf -vvVVHSpQvvRQDJGGLWGfTLTBLQMN -hCmJqVvMSpqqChCJHDZrFsdhrtgFhttZZhts -sfDNqLNpqpzCzLsDqzbCVWRhjTNhShTjHmmjjhStBmvT -wZrlwJwFJGlFMTjhBBZTSTRSbv -wrQrgnPwMsnLbfffVc -hDcwwGWhMMssTcdM -NQmLbNSZHQSHSNpbvfdqfRsZMqssjqdd -LNVtLSSHLSgLNrgwJgJGnBwFMBzD -CRDfCbfjcnRCBVfjVMfMjZpPptplPWtppStpSlBqlq -HdTFLGsdLrzNWtvqPTcpgPZl -JLGmmHrwJGwhjmfMcbDjQC -VShGpPbWjcPCcTLcPN -HqfqDfDFFJDvZRJvqZRRqHZdNcwjllwvQQLQlllccwclCMCT -FddsFmJjjrgGmbSSpS -NRFFLtFtqFLGsdnGbQSs -ljMfMBDlJHgBVHgVflfnwdsSQQbddsSsqnqGfs -PlzDzjljzqRzWzZW -dtzZZbctPzwdlzRwlcdfRgtQJmFmhPSmmSsQQFhsmqSFvm -nDjHnNjjjMnfjNTMWhHQWJSqSSQmhqhm -CDpVCfrjLnnfwtBcpdcbcBZt -sssZSZtDfHbbdtBTCRBzRDFJCBLp -jwWgmWlNQNLlcjWhgQlrQQWrCCJJzFCMVMTzpBMMCVCMTwpT -ggLgrqljLlGvHqttftbP -cSGBFsFcSRZSQGsgBNgVMwMhDQDVfqPjMhwwVq -vnCTLlrpPlHzzjbMfqpbww -rJCnlmClvWvLrTmtTlZcZWSSWPGGdNcFGgcR -lfDDvZZSvLtDtCQZltCqVBWVBCbHJjRdNqWq -pGGhhzMRcqMBqMdVBN -mzgwGrrwhThFGPmGPcFGpwStTfltfDftStDsQRsflDQl -LjnSjLZLBcbBdDqzND -rrfhfMRmpsghfrhGhgQrcPNtZcqNCqdCqPzcNZMM -ZTTgvRpmfffpfgRRhWnVSJJLLWnvJHFlFH -lstcGcttdczzsWVCvQVLCHHnQHWL -rjmJrmfmJMqvQTLvqfGG -JbNrjGjGrMDRJghZggcchhDhzc -tftJQwCgSjpdWHjbRJ -DcwvlZBmGvHjdbczcRpb -sqwDlsBvGNSMQTCNfCTC -DwDrtvMHtBCvcpDcjCMFtBCblJfJGJbZlfzrRlJdbRdZld -sPLPmqhSnLQQSWqlbzRRhfJCJfNJhZ -mVCnWCsQqqLTPWmnDVMFVtHFtMBFpjwM -scChGddJztdNswNsdDsthvmpVmRVcZjmvVvRSMZVSZ -lQLCWgWHCWbFPbbbHqLnLPHHVMpVRgSMmZVSBZBjZVSjRBZp -QrTlTHbPnTsJGtsDdGCr -fMjgFqtFWMhtjcNQSDMmNlCCDMQN -sVHdHdJHwPGPGwwbpJGTbGTvClldmvRSnvlDlLLSlvRnQl -pJbHPHJGVbBswpTcfrBtrhmtrFczzq -SDGSDGVPqqqQPGrTQVTQDrSrJfHJgqhgJqzhJJmWfHpWpzmg -twCdCWMLwbtLLjBddgfcJgRHfRRpfcpRHM -FZdbvFFbVvsWsQsW -rzrRgqGrwgjRVqJCHLzCCWhtDbCC -dTZnNpvBvnJdBpBnsJPvsSCbthLtLbbQShQQLHtSST -BlplPmdlFsslfJmmRfwfwMjw -PPHSrmfHTnmHnHBzRhbFgfbFwzQg -LcsVsGtVLtLqpzwBvgzQRgTTTp -TjLJGTTJWJZZWWZS -tHcshJcJRhLsQscVtccJLRHfvlPjZFSvmvSbvfLFfFFbGZ -drwdTNlwwBTpCdCdwGPrrmjjmjmbSjFPrF -wglnzCDpJtQcztMR -bbMjTbBvgjZNSqldTlVt -wwrcFwsrsnnCQzrCsLnRsQZcNlpJVZHdttZVttSZqJZd -GwLnrsmFCCzqzhvPbPmWmvvfjj -dcnwQdcdrJdSwSFBBqfBfwMqfBfzsh -RgmZpWlCClRlTgBZbhHJJsZjfBHZ -DlNVWgWpgDCCNRDJFcrtQGrrVnrcFPtc -sWSHsdSrHWHsbdsddBsbjmfwffmJDJwcfDQgfvwJDj -ZNGPhRqCCRNGNwSDvmmwwgDhgf -lGlTLTGTSVVFqVTqsFHWntbWBsBsnBHb -QRRgRvDwWDVjmSbDnbTDlDnbqS -rHCPPHrcLFJcllqbTlpq -CldFrNFsgVhhhWgN -qSfMgNqfpmSmlQrRFG -cbBczbtbZTcPWzcrTrmRrLGFTQQFmJ -PBZChtzzcWPcZtBvPjtzBBCfHMMNdDgDpMfVfVpHMqNR -LJPPCHtgtLDfFfvTLwfv -pVGWGGjjjplhpGGVjWnldsvrrMFvfDMTWBdFrfFF -cjlhShjchhjGGmNVjplcQgmTPtHPPJmQgQHgtqgZ diff --git a/days/3/sample.txt b/days/3/sample.txt deleted file mode 100644 index f17e726..0000000 --- a/days/3/sample.txt +++ /dev/null @@ -1,6 +0,0 @@ -vJrwpWtwJgWrhcsFMMfFFhFp -jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL -PmmdzqPrVvPwwTWBwg -wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn -ttgJtRGJQctTZtZT -CrZsJsPPZsGzwwsLwLmpwMDw diff --git a/days/4/day4.go b/days/4/day4.go deleted file mode 100644 index 55cb922..0000000 --- a/days/4/day4.go +++ /dev/null @@ -1,93 +0,0 @@ -package _4 - -import ( - _ "embed" - "fmt" - "strconv" - "strings" - - "github.com/ankon/adventofcode/2022/days" -) - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -func scanRange(s string) ([]int, error) { - minS, maxS, found := strings.Cut(s, "-") - if !found { - return []int{}, fmt.Errorf("invalid range %q", s) - } - - min, err := strconv.ParseInt(minS, 10, 0) - if err != nil { - return []int{}, err - } - max, err := strconv.ParseInt(maxS, 10, 0) - if err != nil { - return []int{}, err - } - return []int{int(min), int(max)}, nil -} - -func rangeFullyContains(r1, r2 []int) bool { - if r1[0] <= r2[0] && r1[1] >= r2[1] { - return true - } - if r1[0] >= r2[0] && r1[1] <= r2[1] { - return true - } - return false -} - -func rangeOverlaps(r1, r2 []int) bool { - if r1[0] <= r2[0] && r1[1] >= r2[0] { - return true - } - if r1[0] <= r2[1] && r1[1] >= r2[1] { - return true - } - if r2[0] <= r1[0] && r2[1] >= r1[1] { - return true - } - if r2[0] <= r1[1] && r2[1] >= r1[1] { - return true - } - return false -} - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - - containedCount := 0 - overlapCount := 0 - for _, pair := range strings.Split(input, "\n") { - if pair == "" { - continue - } - r1, r2, found := strings.Cut(pair, ",") - if !found { - return fmt.Errorf("invalid pair definition %q", pair) - } - range1, err := scanRange(r1) - if err != nil { - return fmt.Errorf("cannot parse range %q: %w", r1, err) - } - range2, err := scanRange(r2) - if err != nil { - return fmt.Errorf("cannot parse range %q: %w", r2, err) - } - if rangeFullyContains(range1, range2) { - containedCount++ - } - if rangeOverlaps(range1, range2) { - overlapCount++ - } - } - fmt.Printf("Pairs with fully contained ranges: %d\n", containedCount) - fmt.Printf("Pairs with overlapping ranges: %d\n", overlapCount) - - return nil -} diff --git a/days/4/input.txt b/days/4/input.txt deleted file mode 100644 index c7fb3fc..0000000 --- a/days/4/input.txt +++ /dev/null @@ -1,1000 +0,0 @@ -48-50,48-49 -5-89,5-5 -17-57,55-96 -24-67,23-25 -89-99,11-89 -34-71,35-71 -13-17,16-95 -13-93,5-12 -11-91,1-11 -4-81,2-11 -53-82,52-53 -5-98,4-97 -4-78,3-3 -20-81,21-80 -79-83,77-82 -76-87,43-87 -14-93,12-62 -13-94,15-95 -22-75,14-53 -67-90,67-79 -1-82,1-82 -5-80,83-96 -28-57,56-56 -53-91,52-54 -21-97,2-36 -8-18,10-98 -7-91,12-91 -11-88,19-95 -22-88,21-88 -31-69,9-48 -2-3,3-43 -5-95,2-6 -5-85,5-79 -51-91,51-69 -41-91,41-64 -23-37,24-95 -1-28,3-94 -6-93,6-98 -8-65,34-66 -2-8,9-38 -3-75,2-4 -40-77,37-76 -51-51,11-51 -95-95,3-94 -90-90,81-90 -26-61,26-61 -1-96,97-98 -41-84,90-91 -94-94,1-94 -52-89,74-90 -9-11,10-74 -57-67,56-62 -29-98,30-78 -20-88,18-54 -11-81,10-82 -85-87,26-86 -8-45,46-78 -16-33,20-49 -73-93,16-93 -35-36,29-36 -4-98,98-98 -24-30,30-80 -64-99,72-97 -8-33,8-47 -88-96,93-99 -23-46,35-49 -41-60,40-41 -5-83,4-6 -76-76,15-76 -37-70,69-71 -11-77,11-12 -57-65,65-97 -20-46,46-62 -76-84,8-77 -10-29,29-53 -16-50,6-17 -20-99,19-19 -11-12,12-72 -24-91,77-92 -37-73,72-73 -50-52,73-89 -37-99,25-76 -1-88,1-2 -18-64,17-63 -19-52,17-52 -5-86,6-87 -13-87,14-87 -23-82,19-92 -56-79,57-79 -25-68,26-67 -5-95,94-96 -38-50,38-39 -32-75,32-75 -23-69,23-69 -25-54,18-25 -33-79,34-67 -38-62,38-65 -62-75,69-78 -2-17,3-17 -12-20,19-96 -7-7,4-8 -1-92,2-93 -29-70,69-77 -7-54,2-54 -9-34,16-34 -4-20,7-31 -4-89,4-47 -12-91,9-96 -8-79,9-80 -32-91,31-91 -1-4,5-55 -85-94,84-95 -73-74,6-74 -51-70,52-70 -21-75,7-27 -13-38,37-39 -42-97,42-98 -33-45,28-45 -12-14,13-98 -91-92,90-91 -66-83,57-83 -8-79,9-67 -59-72,71-72 -33-71,3-33 -13-38,12-38 -18-93,18-52 -28-80,12-26 -87-88,2-88 -7-89,7-85 -26-27,27-27 -12-97,12-97 -36-95,32-91 -25-33,25-32 -4-39,5-75 -40-58,41-58 -8-60,8-93 -9-69,70-70 -19-34,35-68 -47-47,38-47 -1-70,1-70 -39-82,38-83 -17-98,17-99 -56-86,37-56 -2-2,4-96 -5-97,97-97 -52-93,52-77 -39-66,38-66 -9-99,4-99 -25-37,24-37 -2-99,1-98 -13-15,15-15 -10-51,5-9 -38-99,19-96 -6-38,37-78 -94-98,95-99 -8-89,29-89 -2-98,1-98 -13-99,99-99 -1-76,1-25 -8-97,8-97 -9-90,89-93 -24-52,7-49 -30-97,45-99 -26-62,26-59 -15-27,21-30 -80-81,64-80 -65-76,2-76 -9-9,10-99 -3-6,4-82 -78-79,20-79 -11-50,49-49 -10-12,11-68 -1-5,4-85 -8-10,9-95 -16-86,16-87 -11-81,10-11 -36-87,75-87 -55-92,54-99 -3-18,18-84 -4-73,1-2 -16-66,5-76 -29-73,29-79 -60-91,67-91 -82-82,47-82 -31-38,31-37 -44-44,21-44 -93-94,65-94 -13-79,2-12 -4-97,5-97 -40-78,40-41 -69-99,1-69 -8-97,8-96 -27-27,26-79 -60-96,71-88 -24-57,18-25 -1-26,2-27 -53-81,69-81 -3-96,2-96 -9-99,9-97 -45-48,46-56 -6-36,5-30 -45-73,46-73 -28-41,27-42 -4-91,90-94 -6-39,20-44 -3-3,5-65 -17-98,18-65 -15-98,15-96 -29-88,65-90 -10-61,60-62 -26-91,27-91 -78-96,95-95 -6-22,6-17 -40-56,40-57 -4-5,6-98 -78-83,51-83 -8-78,8-78 -26-87,26-86 -4-94,3-4 -5-55,2-6 -40-50,19-56 -55-68,2-94 -39-41,9-40 -68-76,68-69 -51-60,50-59 -9-48,2-10 -13-96,13-63 -1-90,4-91 -1-7,6-99 -25-67,25-66 -13-94,14-93 -27-28,28-70 -39-41,25-40 -8-53,9-53 -56-89,57-88 -4-56,50-56 -22-76,15-17 -7-98,69-76 -12-46,11-46 -1-41,3-72 -43-55,44-76 -9-81,9-81 -45-95,45-94 -12-68,12-69 -90-96,74-85 -67-68,68-68 -50-73,2-73 -6-17,6-97 -70-76,71-99 -9-43,9-43 -9-76,8-75 -66-90,65-66 -13-99,12-14 -1-2,3-91 -53-86,52-53 -3-57,3-96 -81-92,80-92 -6-18,17-88 -70-94,69-69 -17-17,18-88 -4-92,4-93 -41-61,47-61 -25-52,25-73 -78-97,12-97 -39-54,38-46 -39-52,39-58 -8-99,8-51 -52-58,51-52 -5-45,6-46 -3-99,98-98 -84-87,84-98 -58-87,86-88 -6-72,71-73 -41-42,41-86 -27-42,27-77 -14-15,14-74 -43-43,40-43 -17-95,17-93 -44-66,65-70 -4-99,5-99 -43-43,44-86 -64-75,63-71 -4-99,5-99 -6-29,6-99 -19-84,18-83 -72-72,10-72 -9-14,13-88 -3-98,98-98 -9-81,10-81 -13-69,13-70 -3-87,1-87 -22-61,10-62 -75-90,75-90 -69-99,68-87 -94-94,91-95 -2-3,3-96 -5-93,48-93 -43-45,33-49 -85-87,2-86 -51-52,52-62 -50-91,40-49 -1-81,21-81 -51-56,51-56 -22-23,23-37 -25-27,26-67 -58-59,23-58 -37-85,84-85 -12-97,12-96 -14-38,2-13 -33-81,32-44 -34-65,46-60 -3-28,27-28 -11-54,11-55 -2-93,1-93 -28-28,28-50 -10-82,81-83 -77-82,77-82 -33-63,49-63 -2-84,89-91 -37-90,36-91 -46-85,45-85 -97-97,14-97 -5-18,6-19 -7-94,6-95 -17-87,12-86 -11-85,39-85 -7-94,7-93 -9-98,9-96 -18-18,19-96 -62-62,34-62 -24-36,24-91 -72-91,4-91 -7-84,7-83 -9-93,9-87 -22-99,21-99 -32-46,31-32 -32-70,69-97 -13-89,12-88 -10-10,11-89 -46-46,47-64 -51-51,24-52 -5-51,3-3 -46-90,99-99 -6-96,5-95 -50-96,50-97 -96-96,4-70 -13-36,12-35 -19-90,13-20 -12-43,42-95 -1-83,1-84 -3-5,4-70 -24-97,25-98 -27-40,1-50 -37-82,36-83 -47-95,47-94 -2-80,2-58 -64-83,63-87 -42-52,41-44 -26-97,1-97 -35-45,35-78 -6-45,28-82 -11-17,11-16 -67-67,44-67 -2-95,2-94 -22-95,22-94 -20-43,21-92 -33-60,59-76 -6-75,7-75 -3-90,96-99 -38-76,41-76 -18-98,6-19 -2-65,64-77 -3-88,2-88 -14-94,13-93 -40-89,71-99 -44-93,44-72 -48-62,48-61 -6-27,6-26 -43-53,43-54 -4-97,36-98 -8-13,12-83 -15-96,7-96 -18-91,17-18 -11-13,12-55 -31-92,19-94 -44-87,14-45 -18-51,17-18 -23-24,27-27 -23-46,24-88 -12-90,13-90 -37-70,34-70 -1-98,88-98 -2-93,6-95 -73-99,74-98 -4-46,2-46 -50-52,51-75 -45-91,46-90 -11-85,58-94 -26-43,26-44 -56-95,55-94 -10-93,11-92 -1-99,1-99 -8-95,7-7 -19-69,9-18 -18-90,9-60 -74-93,13-73 -62-90,61-72 -7-53,52-95 -44-82,4-44 -17-88,17-88 -26-27,26-89 -1-9,1-62 -13-40,39-62 -2-93,1-92 -91-91,17-91 -57-58,58-85 -23-98,97-99 -16-48,16-48 -25-61,61-87 -14-47,13-84 -46-96,47-94 -8-98,7-99 -3-5,4-97 -38-83,28-82 -7-99,6-34 -23-91,38-84 -33-35,34-63 -14-55,55-55 -34-50,11-35 -3-69,4-69 -67-99,99-99 -38-94,2-59 -2-98,2-97 -77-79,42-78 -6-45,44-45 -39-79,61-93 -5-92,5-97 -4-61,3-64 -47-48,48-67 -11-23,10-23 -2-99,9-99 -31-99,30-81 -28-87,29-88 -8-31,2-13 -3-17,16-83 -29-58,57-59 -4-75,15-35 -49-94,48-93 -23-85,84-84 -7-92,7-97 -53-91,91-97 -26-95,1-95 -9-22,7-9 -13-63,62-95 -54-55,54-97 -80-88,79-88 -1-44,2-44 -3-83,1-4 -95-95,26-95 -23-26,23-26 -19-35,19-34 -17-34,34-34 -39-89,75-97 -42-84,84-84 -60-95,61-94 -6-88,5-88 -2-68,1-68 -16-76,15-16 -30-93,9-96 -10-91,11-91 -36-88,35-36 -24-67,45-66 -41-58,16-96 -84-85,83-85 -10-59,18-59 -33-70,69-69 -58-69,57-58 -4-6,68-85 -3-91,91-91 -99-99,2-98 -33-94,93-95 -68-69,27-68 -4-4,5-14 -98-98,2-97 -5-91,90-92 -2-91,2-90 -37-81,80-80 -9-51,54-69 -45-59,46-59 -8-69,7-69 -20-21,21-29 -45-83,88-91 -22-87,20-21 -4-77,3-76 -50-81,49-49 -47-59,58-78 -22-85,21-84 -3-86,7-91 -63-83,62-63 -10-58,7-57 -14-88,14-88 -18-67,16-28 -39-50,39-42 -9-85,8-85 -7-28,7-8 -72-72,19-73 -25-27,25-56 -40-43,40-43 -10-26,25-25 -29-99,30-99 -9-14,13-92 -9-17,10-56 -93-94,1-94 -31-67,30-68 -15-84,84-84 -45-46,8-46 -10-93,10-94 -31-48,5-94 -49-93,92-92 -45-80,40-67 -63-94,7-93 -2-94,1-66 -26-44,41-53 -51-94,1-94 -5-93,4-92 -14-86,85-86 -9-52,8-10 -24-61,23-62 -1-78,77-79 -6-97,17-96 -43-65,19-43 -45-99,35-99 -58-58,20-57 -22-89,64-85 -12-22,21-80 -6-36,36-36 -1-92,87-92 -26-99,26-97 -7-85,1-85 -20-98,20-98 -2-51,2-54 -73-95,74-95 -16-54,15-17 -4-95,4-96 -11-98,11-98 -67-79,66-80 -61-61,62-63 -50-62,12-50 -9-80,9-81 -1-1,3-87 -16-61,15-23 -31-35,34-40 -13-89,12-90 -89-91,90-95 -20-60,12-81 -2-65,1-66 -38-96,56-96 -23-23,12-22 -96-96,11-95 -8-37,36-97 -2-26,1-26 -30-71,37-73 -71-87,70-70 -31-99,31-82 -6-39,2-7 -1-99,3-99 -29-73,32-81 -33-37,33-36 -15-41,14-40 -32-33,33-90 -23-85,22-24 -26-93,26-86 -3-97,2-98 -10-92,92-94 -29-55,30-55 -9-75,29-96 -6-94,93-97 -63-63,52-63 -24-78,5-5 -38-67,37-67 -14-32,13-32 -35-94,36-94 -23-92,24-92 -9-36,8-36 -63-95,62-62 -37-78,3-78 -34-51,17-37 -84-85,13-84 -1-95,1-98 -18-56,18-19 -17-78,13-16 -6-52,15-44 -13-33,14-33 -10-88,11-89 -61-80,61-79 -6-98,98-98 -1-91,1-85 -60-86,10-87 -3-96,95-98 -34-99,33-98 -19-21,20-91 -7-96,8-96 -2-90,2-90 -36-96,36-96 -76-96,60-75 -8-44,7-44 -9-28,10-28 -10-95,7-95 -56-68,29-82 -10-97,18-99 -68-97,45-97 -19-92,2-92 -6-97,5-97 -74-74,73-73 -20-70,20-70 -18-66,19-67 -91-94,7-92 -4-47,4-47 -11-93,12-93 -33-54,32-53 -54-64,55-63 -20-99,20-21 -39-82,56-68 -4-36,36-47 -30-41,25-31 -65-69,69-69 -20-71,71-74 -16-36,24-54 -2-96,95-98 -11-70,10-12 -5-36,35-95 -36-92,36-37 -37-78,32-87 -28-89,15-88 -9-63,62-62 -2-94,4-94 -85-85,72-85 -30-73,7-31 -10-36,10-36 -75-97,47-95 -23-23,4-24 -49-88,36-87 -25-25,26-42 -33-86,26-86 -13-76,76-76 -60-60,60-60 -3-23,24-24 -4-85,10-85 -7-38,8-37 -40-85,41-84 -46-86,47-87 -8-38,7-38 -76-78,9-77 -80-94,57-94 -86-96,86-97 -35-89,10-67 -45-94,35-81 -8-93,7-8 -22-48,23-47 -21-94,20-94 -63-72,60-73 -89-89,57-90 -34-41,41-78 -5-5,2-6 -1-79,1-80 -79-82,80-83 -37-37,38-53 -65-93,64-96 -33-85,33-33 -7-98,44-57 -2-5,4-69 -19-69,18-68 -80-81,7-81 -19-99,20-99 -5-34,4-14 -4-88,88-89 -51-91,59-93 -33-60,33-58 -32-67,27-94 -8-98,7-8 -34-43,44-69 -10-80,10-11 -7-73,11-73 -23-69,24-69 -68-83,6-68 -2-35,5-35 -1-4,3-90 -88-89,30-89 -57-99,14-63 -16-29,17-28 -67-82,62-77 -20-65,19-66 -37-69,61-63 -58-94,94-94 -1-72,72-72 -7-11,10-47 -18-59,59-59 -57-57,37-58 -60-81,54-72 -2-86,1-87 -7-78,7-77 -59-69,59-65 -15-16,15-73 -15-82,16-92 -8-88,57-88 -36-92,36-88 -59-60,24-59 -4-22,1-3 -44-60,45-60 -90-95,35-89 -21-30,20-30 -4-83,83-83 -16-99,7-17 -11-18,19-95 -45-94,44-94 -3-11,3-12 -9-70,8-10 -1-8,8-78 -1-5,4-97 -30-55,29-31 -7-89,8-89 -47-47,46-48 -66-96,38-84 -33-34,33-73 -2-23,1-22 -52-64,53-91 -9-34,19-61 -25-57,25-57 -1-98,97-98 -79-89,76-80 -28-80,28-80 -13-77,76-78 -3-88,2-88 -69-72,70-72 -91-91,22-91 -77-95,76-94 -84-92,84-91 -55-99,56-99 -1-91,2-91 -33-36,27-36 -79-84,62-74 -52-54,18-53 -26-37,25-27 -55-85,40-85 -58-74,10-59 -6-53,6-53 -42-49,42-47 -47-79,80-97 -11-24,25-91 -83-87,86-87 -1-88,1-96 -55-63,54-62 -76-76,8-76 -3-78,78-99 -1-86,8-96 -44-70,43-70 -25-27,26-91 -65-98,97-97 -14-64,15-65 -9-36,8-35 -78-84,77-85 -42-58,41-59 -60-92,59-60 -95-97,14-86 -8-82,7-83 -5-58,5-59 -5-99,6-99 -4-13,1-4 -57-86,43-58 -11-82,11-11 -4-87,1-5 -6-7,7-11 -6-22,2-7 -15-49,14-49 -39-97,99-99 -12-49,13-90 -70-80,71-80 -46-95,66-94 -94-98,13-94 -3-11,11-11 -13-23,12-23 -11-98,11-98 -20-99,8-20 -28-87,27-87 -16-21,21-61 -2-91,7-56 -7-7,8-71 -74-74,67-74 -23-88,1-74 -1-99,2-98 -34-85,40-86 -6-85,6-68 -28-31,31-49 -13-40,13-40 -55-56,56-56 -70-72,26-71 -93-94,34-93 -45-75,44-75 -4-10,10-50 -65-74,65-77 -39-87,6-59 -11-85,3-85 -8-46,12-46 -9-9,10-95 -30-41,27-92 -13-97,9-96 -21-62,22-63 -54-69,52-53 -17-99,18-99 -75-92,7-76 -38-39,38-90 -50-69,49-50 -65-87,65-99 -6-98,6-96 -34-62,40-90 -33-47,34-48 -33-95,34-95 -42-99,43-98 -70-85,1-71 -37-63,38-63 -12-17,17-72 -28-31,29-92 -18-69,8-17 -41-96,40-95 -7-86,7-86 -68-78,67-73 -4-6,7-99 -8-86,86-87 -5-6,6-37 -88-94,89-95 -33-74,33-74 -86-87,86-87 -29-55,62-78 -23-38,13-38 -9-44,10-89 -18-67,19-97 -3-83,1-66 -55-81,55-81 -6-72,7-71 -5-55,6-55 -14-99,14-97 -39-83,16-40 -11-73,55-73 -4-68,5-67 -66-73,26-73 -3-92,3-91 -36-59,33-35 -72-73,4-73 -1-83,2-83 -25-88,25-43 -45-71,45-73 -9-96,95-95 -4-5,7-23 -48-50,4-49 -45-96,44-96 -50-87,49-50 -98-99,27-96 -4-40,40-78 -3-94,94-94 -7-34,25-26 -72-79,23-72 -2-84,3-83 -78-96,25-78 -77-94,73-94 -63-66,62-65 -25-80,24-80 -10-33,78-90 -25-55,24-54 -58-62,23-64 -61-62,62-84 -83-83,46-84 -23-30,31-92 -8-95,94-99 -35-65,34-64 -12-19,12-18 -21-25,24-43 -54-79,54-84 -37-56,37-57 -77-77,15-77 -57-88,55-88 -7-93,8-93 -5-89,3-66 -33-63,32-33 -9-52,51-96 -7-97,6-66 -3-58,1-3 -26-85,25-84 -11-63,10-12 -52-54,53-54 -23-68,22-22 -14-96,14-95 -4-41,3-21 -4-6,5-83 -97-98,1-97 -13-90,73-88 -11-15,7-10 -65-80,24-81 -48-82,48-83 -81-87,4-81 -40-47,40-47 -15-87,14-75 -30-50,29-30 -26-65,64-64 -37-37,7-37 -51-51,49-51 -5-71,7-70 -18-54,53-54 -47-48,48-60 -26-98,25-97 -5-6,5-81 -3-98,3-99 -9-22,21-22 -4-97,1-1 -36-36,37-77 -22-35,4-23 -18-95,19-96 -14-94,14-96 -43-46,47-50 -80-91,81-91 -20-67,5-81 -8-87,9-86 -30-69,23-30 -96-99,2-96 -59-75,74-76 -20-66,19-66 -10-85,10-65 -9-82,8-38 -32-66,54-66 -23-64,63-65 -1-89,1-90 -1-95,1-94 -12-82,7-64 -55-66,60-66 -3-93,3-42 -45-87,15-88 -3-50,3-76 -7-86,8-79 -39-39,40-85 -57-86,52-52 -17-84,16-18 -63-99,64-99 -83-94,83-94 -12-85,11-86 -18-89,17-17 -12-25,13-87 -9-12,10-15 -62-92,85-88 -26-97,26-94 -16-94,94-94 -47-83,47-83 -25-86,85-88 -1-99,1-98 -47-87,87-99 -9-99,9-97 -8-73,2-73 -45-47,46-85 -18-95,18-96 -41-41,40-41 -1-4,4-61 -4-95,5-96 -8-79,78-80 -6-81,9-81 -7-90,1-7 -6-22,6-22 -32-82,15-59 -19-93,13-93 -43-48,12-99 -45-45,46-59 -27-69,1-28 -78-78,59-79 -12-57,57-57 -4-39,4-77 -55-91,91-91 -27-87,92-95 -83-87,87-98 -22-84,22-31 -3-91,3-22 -45-86,57-62 -68-82,55-82 -96-98,3-97 -12-32,1-32 -37-71,37-71 -31-59,31-59 -86-88,79-88 -4-92,3-3 -40-91,17-91 -51-52,52-74 -2-97,1-98 -50-83,82-83 -34-34,35-41 -6-47,5-5 -5-65,5-47 -32-77,33-85 -21-68,22-67 -12-45,46-95 -45-48,38-46 -39-84,35-40 -4-60,3-4 -67-83,68-84 -24-92,25-93 diff --git a/days/4/sample.txt b/days/4/sample.txt deleted file mode 100644 index 9f9e9cf..0000000 --- a/days/4/sample.txt +++ /dev/null @@ -1,6 +0,0 @@ -2-4,6-8 -2-3,4-5 -5-7,7-9 -2-8,3-7 -6-6,4-6 -2-6,4-8 diff --git a/days/5/day5.go b/days/5/day5.go deleted file mode 100644 index e344f73..0000000 --- a/days/5/day5.go +++ /dev/null @@ -1,167 +0,0 @@ -package _5 - -import ( - _ "embed" - "fmt" - "math" - "strings" - - "github.com/ankon/adventofcode/2022/days" - "github.com/ankon/adventofcode/2022/utils" -) - -type crateStack = utils.Stack[byte] - -type action struct { - from int - to int - count int -} - -type parseState int -const ( - parsing_stacks parseState = 1 - parsing_actions parseState = 2 -) - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -func simulateActionsCrateMover9000(stacks []crateStack, actions []action) error { - for _, action := range actions { - for i := 0; i < action.count; i++ { - x := stacks[action.from - 1].Pop() - stacks[action.to - 1].Push(x) - } - } - return nil -} - -func simulateActionsCrateMover9001(stacks []crateStack, actions []action) error { - for _, action := range actions { - if action.count == 1 { - x := stacks[action.from - 1].Pop() - stacks[action.to - 1].Push(x) - } else { - helper := crateStack{} - for i := 0; i < action.count; i++ { - x := stacks[action.from - 1].Pop() - helper.Push(x) - } - for i := 0; i < action.count; i++ { - x := helper.Pop() - stacks[action.to - 1].Push(x) - } - } - } - return nil -} - -func parseAction(l string) (action, error) { - var count, from, to int - - n, err := fmt.Sscanf(l, "move %d from %d to %d", &count, &from, &to) - if err != nil { - return action{}, err - } - if n != 3 { - return action{}, fmt.Errorf("unexpected number of fields %d, expected 3", n) - } - return action{from,to,count}, nil -} - -func parseStacks(stackLines []string) ([]crateStack, error) { - stackNames := stackLines[len(stackLines) - 1] - stacks := make([]crateStack, int(math.Ceil(float64(len(stackNames)) / 4))) - for i := len(stackLines) - 2; i >= 0; i-- { - stackLine := stackLines[i] - for s := 0; s < (len(stackLine) + 1) / 4; s++ { - var crate byte - n, err := fmt.Sscanf(stackLine[s*4:], "[%c]", &crate) - if err == nil { - if n != 1 { - return nil, fmt.Errorf("expected 1 result, got %d", n) - } - stacks[s].Push(crate) - } - } - } - - return stacks, nil -} - -func parseInput(input string) (stacks []crateStack, actions []action, err error) { - s := parsing_stacks - stackLines := []string{} - - // Read lines until empty line - // Line before empty line: Stack ids - // Lines before that: stack contents - // Read actions - for _, line := range strings.Split(input, "\n") { - if s == parsing_stacks { - if line == "" { - stacks, err = parseStacks(stackLines) - if err != nil { - return nil, nil, err - } - s = parsing_actions - } else { - stackLines = append(stackLines, line) - } - } else if s == parsing_actions { - if line == "" { - break - } - - action, err := parseAction(line) - if err != nil { - return nil, nil, err - } - - actions = append(actions, action) - } - } - - return stacks, actions, nil -} - -func getTopCrates(stacks []crateStack) string { - result := "" - for _, stack := range stacks { - result += string(stack.Top()) - } - return result -} - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - inputStacks, actions, err := parseInput(input) - if err != nil { - return fmt.Errorf("cannot parse input: %w", err) - } - - stacks := make([]crateStack, len(inputStacks)) - for i, stack := range inputStacks { - stacks[i] = stack.Clone() - } - err = simulateActionsCrateMover9000(stacks, actions) - if err != nil { - return fmt.Errorf("cannot simulate actions: %w", err) - } - fmt.Printf("Top crates (CrateMover 9000): %s\n", getTopCrates(stacks)) - - for i, stack := range inputStacks { - stacks[i] = stack.Clone() - } - err = simulateActionsCrateMover9001(stacks, actions) - if err != nil { - return fmt.Errorf("cannot simulate actions: %w", err) - } - fmt.Printf("Top crates (CrateMover 9001): %s\n", getTopCrates(stacks)) - - return nil -} diff --git a/days/5/input.txt b/days/5/input.txt deleted file mode 100644 index 198d0b7..0000000 --- a/days/5/input.txt +++ /dev/null @@ -1,514 +0,0 @@ -[N] [C] [Q] -[W] [J] [L] [J] [V] -[F] [N] [D] [L] [S] [W] -[R] [S] [F] [G] [R] [V] [Z] -[Z] [G] [Q] [C] [W] [C] [F] [G] -[S] [Q] [V] [P] [S] [F] [D] [R] [S] -[M] [P] [R] [Z] [P] [D] [N] [N] [M] -[D] [W] [W] [F] [T] [H] [Z] [W] [R] - 1 2 3 4 5 6 7 8 9 - -move 1 from 3 to 9 -move 3 from 5 to 3 -move 4 from 2 to 5 -move 4 from 1 to 2 -move 3 from 5 to 7 -move 3 from 1 to 2 -move 4 from 8 to 7 -move 4 from 9 to 7 -move 4 from 2 to 7 -move 2 from 3 to 6 -move 3 from 6 to 2 -move 5 from 4 to 7 -move 7 from 3 to 7 -move 5 from 6 to 9 -move 2 from 4 to 8 -move 1 from 3 to 2 -move 4 from 2 to 7 -move 2 from 2 to 8 -move 8 from 8 to 5 -move 1 from 2 to 4 -move 1 from 2 to 9 -move 7 from 5 to 4 -move 31 from 7 to 1 -move 9 from 9 to 3 -move 12 from 1 to 9 -move 15 from 1 to 7 -move 4 from 3 to 8 -move 2 from 5 to 1 -move 12 from 7 to 5 -move 2 from 8 to 2 -move 12 from 5 to 4 -move 1 from 3 to 5 -move 6 from 1 to 3 -move 1 from 1 to 5 -move 1 from 8 to 7 -move 1 from 8 to 5 -move 7 from 7 to 8 -move 5 from 8 to 2 -move 11 from 4 to 2 -move 10 from 3 to 1 -move 1 from 7 to 5 -move 10 from 1 to 3 -move 5 from 4 to 2 -move 1 from 4 to 6 -move 7 from 2 to 3 -move 9 from 9 to 5 -move 15 from 2 to 3 -move 1 from 9 to 1 -move 7 from 5 to 3 -move 1 from 2 to 4 -move 2 from 9 to 2 -move 1 from 8 to 9 -move 5 from 5 to 3 -move 1 from 8 to 7 -move 1 from 2 to 4 -move 1 from 7 to 6 -move 1 from 1 to 6 -move 1 from 6 to 9 -move 1 from 5 to 4 -move 1 from 6 to 4 -move 1 from 6 to 8 -move 2 from 9 to 4 -move 12 from 3 to 1 -move 8 from 4 to 8 -move 1 from 9 to 8 -move 10 from 8 to 6 -move 1 from 6 to 7 -move 6 from 6 to 9 -move 1 from 2 to 7 -move 1 from 4 to 7 -move 2 from 7 to 3 -move 1 from 1 to 3 -move 6 from 9 to 1 -move 2 from 6 to 7 -move 12 from 1 to 3 -move 5 from 1 to 9 -move 1 from 7 to 3 -move 38 from 3 to 7 -move 19 from 7 to 8 -move 19 from 8 to 2 -move 1 from 9 to 6 -move 5 from 3 to 7 -move 2 from 6 to 7 -move 1 from 3 to 9 -move 2 from 3 to 6 -move 4 from 2 to 6 -move 6 from 2 to 4 -move 14 from 7 to 9 -move 8 from 2 to 5 -move 19 from 9 to 3 -move 6 from 4 to 1 -move 6 from 1 to 4 -move 4 from 4 to 3 -move 10 from 7 to 6 -move 1 from 6 to 4 -move 22 from 3 to 1 -move 5 from 1 to 6 -move 5 from 5 to 8 -move 1 from 7 to 4 -move 1 from 2 to 3 -move 15 from 6 to 9 -move 3 from 8 to 4 -move 2 from 3 to 1 -move 6 from 9 to 1 -move 1 from 3 to 9 -move 1 from 3 to 1 -move 1 from 5 to 9 -move 1 from 7 to 1 -move 1 from 8 to 2 -move 6 from 9 to 2 -move 2 from 9 to 1 -move 3 from 6 to 3 -move 2 from 9 to 5 -move 1 from 6 to 7 -move 2 from 2 to 7 -move 3 from 3 to 5 -move 1 from 8 to 9 -move 7 from 4 to 7 -move 1 from 6 to 3 -move 2 from 9 to 5 -move 10 from 1 to 5 -move 19 from 1 to 8 -move 9 from 7 to 1 -move 1 from 3 to 5 -move 2 from 2 to 4 -move 2 from 2 to 6 -move 2 from 6 to 4 -move 7 from 1 to 7 -move 3 from 7 to 3 -move 2 from 4 to 1 -move 3 from 3 to 4 -move 1 from 2 to 4 -move 2 from 4 to 1 -move 2 from 4 to 8 -move 20 from 8 to 2 -move 1 from 8 to 3 -move 4 from 7 to 8 -move 14 from 2 to 6 -move 3 from 1 to 2 -move 2 from 1 to 7 -move 1 from 4 to 6 -move 1 from 1 to 5 -move 4 from 2 to 8 -move 3 from 7 to 6 -move 1 from 4 to 6 -move 2 from 7 to 9 -move 1 from 2 to 6 -move 1 from 3 to 1 -move 3 from 5 to 8 -move 1 from 1 to 4 -move 2 from 9 to 5 -move 4 from 6 to 7 -move 1 from 4 to 1 -move 1 from 8 to 5 -move 1 from 7 to 6 -move 1 from 2 to 9 -move 2 from 7 to 1 -move 1 from 1 to 3 -move 1 from 7 to 2 -move 4 from 2 to 7 -move 1 from 1 to 3 -move 2 from 3 to 2 -move 9 from 8 to 3 -move 1 from 8 to 6 -move 2 from 7 to 3 -move 1 from 7 to 4 -move 1 from 9 to 7 -move 1 from 7 to 2 -move 2 from 2 to 8 -move 6 from 5 to 2 -move 5 from 3 to 7 -move 1 from 4 to 7 -move 3 from 7 to 1 -move 11 from 5 to 8 -move 2 from 1 to 6 -move 2 from 1 to 8 -move 2 from 5 to 9 -move 1 from 7 to 2 -move 2 from 5 to 4 -move 17 from 6 to 7 -move 1 from 4 to 1 -move 1 from 1 to 7 -move 1 from 6 to 5 -move 1 from 6 to 2 -move 9 from 2 to 5 -move 1 from 6 to 7 -move 9 from 7 to 4 -move 3 from 7 to 8 -move 3 from 3 to 4 -move 8 from 7 to 9 -move 11 from 8 to 1 -move 1 from 4 to 3 -move 1 from 7 to 4 -move 9 from 9 to 4 -move 5 from 1 to 7 -move 8 from 5 to 1 -move 3 from 3 to 4 -move 6 from 7 to 9 -move 3 from 8 to 5 -move 1 from 3 to 8 -move 1 from 5 to 8 -move 2 from 9 to 1 -move 3 from 9 to 7 -move 2 from 7 to 9 -move 3 from 9 to 8 -move 1 from 7 to 3 -move 1 from 3 to 9 -move 7 from 4 to 3 -move 18 from 4 to 2 -move 8 from 1 to 6 -move 1 from 6 to 7 -move 2 from 3 to 1 -move 14 from 2 to 6 -move 5 from 1 to 6 -move 5 from 3 to 2 -move 2 from 9 to 5 -move 3 from 1 to 8 -move 1 from 7 to 9 -move 3 from 5 to 1 -move 4 from 8 to 4 -move 1 from 2 to 7 -move 6 from 2 to 5 -move 2 from 1 to 6 -move 14 from 6 to 1 -move 2 from 4 to 7 -move 2 from 4 to 6 -move 12 from 1 to 6 -move 8 from 8 to 3 -move 11 from 6 to 1 -move 1 from 1 to 6 -move 15 from 6 to 9 -move 3 from 7 to 3 -move 11 from 1 to 4 -move 3 from 5 to 3 -move 10 from 9 to 5 -move 2 from 6 to 9 -move 2 from 2 to 5 -move 6 from 3 to 7 -move 7 from 9 to 3 -move 2 from 1 to 8 -move 1 from 9 to 6 -move 12 from 3 to 4 -move 13 from 5 to 6 -move 2 from 7 to 4 -move 3 from 7 to 5 -move 2 from 8 to 4 -move 15 from 6 to 5 -move 22 from 4 to 5 -move 2 from 3 to 6 -move 1 from 7 to 8 -move 2 from 1 to 2 -move 13 from 5 to 3 -move 1 from 8 to 6 -move 1 from 6 to 4 -move 1 from 2 to 7 -move 7 from 5 to 2 -move 4 from 4 to 8 -move 1 from 6 to 3 -move 3 from 5 to 6 -move 2 from 8 to 9 -move 4 from 5 to 1 -move 1 from 9 to 8 -move 4 from 2 to 5 -move 1 from 7 to 6 -move 4 from 6 to 3 -move 1 from 6 to 9 -move 1 from 9 to 6 -move 4 from 1 to 6 -move 1 from 9 to 4 -move 4 from 6 to 3 -move 1 from 6 to 4 -move 14 from 5 to 6 -move 23 from 3 to 1 -move 2 from 5 to 6 -move 1 from 4 to 2 -move 6 from 5 to 7 -move 16 from 6 to 5 -move 2 from 2 to 6 -move 2 from 6 to 1 -move 2 from 2 to 4 -move 1 from 2 to 8 -move 15 from 1 to 3 -move 4 from 8 to 2 -move 9 from 1 to 8 -move 12 from 5 to 7 -move 2 from 5 to 1 -move 1 from 4 to 6 -move 1 from 5 to 6 -move 3 from 7 to 3 -move 2 from 8 to 6 -move 1 from 2 to 3 -move 2 from 3 to 5 -move 3 from 1 to 9 -move 12 from 3 to 9 -move 4 from 9 to 7 -move 2 from 9 to 5 -move 4 from 8 to 5 -move 8 from 7 to 2 -move 6 from 5 to 8 -move 2 from 5 to 7 -move 12 from 7 to 1 -move 2 from 6 to 7 -move 11 from 2 to 4 -move 1 from 6 to 5 -move 1 from 5 to 8 -move 10 from 8 to 6 -move 7 from 1 to 9 -move 3 from 3 to 8 -move 2 from 7 to 4 -move 1 from 5 to 3 -move 9 from 4 to 7 -move 16 from 9 to 6 -move 2 from 1 to 6 -move 1 from 7 to 8 -move 2 from 4 to 1 -move 1 from 1 to 5 -move 1 from 5 to 7 -move 2 from 3 to 9 -move 5 from 4 to 6 -move 1 from 3 to 6 -move 1 from 4 to 5 -move 1 from 5 to 8 -move 16 from 6 to 5 -move 2 from 7 to 6 -move 21 from 6 to 2 -move 3 from 8 to 7 -move 1 from 9 to 1 -move 7 from 7 to 1 -move 14 from 2 to 5 -move 1 from 9 to 3 -move 1 from 3 to 1 -move 1 from 8 to 3 -move 2 from 2 to 6 -move 15 from 5 to 1 -move 20 from 1 to 8 -move 1 from 3 to 5 -move 4 from 2 to 8 -move 2 from 1 to 2 -move 2 from 6 to 8 -move 3 from 7 to 6 -move 2 from 6 to 7 -move 1 from 7 to 2 -move 6 from 5 to 6 -move 3 from 5 to 9 -move 2 from 9 to 6 -move 1 from 9 to 4 -move 2 from 2 to 3 -move 1 from 3 to 2 -move 2 from 1 to 4 -move 1 from 3 to 9 -move 2 from 4 to 7 -move 4 from 8 to 4 -move 8 from 8 to 6 -move 5 from 6 to 9 -move 6 from 6 to 7 -move 6 from 6 to 3 -move 5 from 3 to 2 -move 2 from 2 to 3 -move 10 from 7 to 1 -move 2 from 5 to 2 -move 2 from 4 to 1 -move 5 from 5 to 9 -move 2 from 3 to 5 -move 2 from 9 to 4 -move 5 from 4 to 8 -move 8 from 9 to 6 -move 16 from 1 to 9 -move 7 from 2 to 7 -move 10 from 9 to 4 -move 10 from 4 to 8 -move 1 from 7 to 3 -move 1 from 2 to 5 -move 3 from 5 to 7 -move 2 from 3 to 6 -move 5 from 7 to 4 -move 4 from 4 to 5 -move 17 from 8 to 3 -move 9 from 6 to 2 -move 17 from 3 to 9 -move 9 from 8 to 3 -move 2 from 5 to 6 -move 1 from 5 to 8 -move 5 from 2 to 4 -move 1 from 6 to 9 -move 3 from 9 to 5 -move 3 from 7 to 4 -move 13 from 9 to 3 -move 3 from 9 to 2 -move 1 from 9 to 8 -move 2 from 6 to 4 -move 9 from 3 to 4 -move 3 from 9 to 3 -move 1 from 8 to 1 -move 2 from 5 to 2 -move 5 from 4 to 7 -move 1 from 9 to 2 -move 6 from 7 to 2 -move 1 from 9 to 6 -move 9 from 2 to 4 -move 1 from 1 to 7 -move 1 from 6 to 5 -move 1 from 7 to 4 -move 4 from 4 to 2 -move 12 from 3 to 6 -move 7 from 2 to 5 -move 1 from 2 to 1 -move 1 from 1 to 9 -move 2 from 2 to 6 -move 5 from 8 to 2 -move 8 from 6 to 3 -move 1 from 9 to 3 -move 4 from 2 to 7 -move 1 from 3 to 2 -move 2 from 2 to 7 -move 1 from 2 to 5 -move 3 from 6 to 3 -move 10 from 5 to 8 -move 1 from 5 to 3 -move 1 from 6 to 5 -move 5 from 8 to 7 -move 1 from 5 to 8 -move 2 from 6 to 3 -move 5 from 7 to 4 -move 3 from 3 to 6 -move 2 from 8 to 6 -move 3 from 8 to 2 -move 1 from 3 to 7 -move 15 from 4 to 5 -move 10 from 4 to 1 -move 7 from 3 to 5 -move 1 from 2 to 9 -move 5 from 5 to 7 -move 8 from 5 to 9 -move 4 from 3 to 6 -move 3 from 9 to 6 -move 3 from 1 to 4 -move 10 from 7 to 4 -move 2 from 2 to 4 -move 2 from 3 to 5 -move 1 from 7 to 2 -move 1 from 7 to 6 -move 6 from 6 to 5 -move 7 from 5 to 3 -move 1 from 8 to 3 -move 5 from 1 to 6 -move 9 from 5 to 3 -move 14 from 4 to 7 -move 1 from 2 to 8 -move 1 from 8 to 2 -move 1 from 6 to 4 -move 2 from 4 to 7 -move 1 from 2 to 9 -move 1 from 4 to 8 -move 2 from 1 to 4 -move 8 from 6 to 1 -move 1 from 4 to 3 -move 1 from 5 to 8 -move 12 from 7 to 3 -move 1 from 4 to 8 -move 7 from 9 to 1 -move 3 from 6 to 2 -move 3 from 8 to 7 -move 1 from 2 to 9 -move 4 from 7 to 1 -move 6 from 1 to 7 -move 2 from 2 to 8 -move 7 from 7 to 3 -move 10 from 1 to 6 -move 20 from 3 to 1 -move 2 from 6 to 7 -move 1 from 9 to 1 -move 8 from 6 to 8 -move 6 from 8 to 9 -move 5 from 3 to 7 -move 2 from 7 to 3 -move 2 from 9 to 2 -move 5 from 1 to 3 -move 2 from 9 to 8 -move 8 from 3 to 7 -move 6 from 8 to 3 -move 1 from 9 to 8 -move 19 from 1 to 6 -move 17 from 3 to 6 -move 2 from 2 to 4 -move 1 from 3 to 5 -move 1 from 4 to 1 -move 1 from 4 to 8 -move 2 from 8 to 5 -move 1 from 5 to 1 -move 1 from 5 to 4 -move 1 from 5 to 7 -move 2 from 1 to 3 -move 15 from 7 to 4 -move 1 from 9 to 7 -move 2 from 7 to 6 -move 21 from 6 to 4 -move 17 from 6 to 8 -move 2 from 3 to 5 -move 29 from 4 to 9 -move 15 from 9 to 7 -move 1 from 5 to 1 -move 9 from 8 to 2 -move 10 from 9 to 3 -move 8 from 2 to 6 diff --git a/days/5/sample.txt b/days/5/sample.txt deleted file mode 100644 index 84933bb..0000000 --- a/days/5/sample.txt +++ /dev/null @@ -1,9 +0,0 @@ - [D] -[N] [C] -[Z] [M] [P] - 1 2 3 - -move 1 from 2 to 1 -move 3 from 1 to 3 -move 2 from 2 to 1 -move 1 from 1 to 2 diff --git a/days/6/day6.go b/days/6/day6.go deleted file mode 100644 index f3fdb23..0000000 --- a/days/6/day6.go +++ /dev/null @@ -1,84 +0,0 @@ -package _6 - -import ( - _ "embed" - "fmt" -) - -type expected struct { - packet int - message int -} - -type requiredLength int -const ( - startOfPacket requiredLength = 4 - startOfMessage requiredLength = 14 -) - -var knownInputs = map[string]expected{ - "mjqjpqmgbljsphdztnvjfqwrcgsmlb": {7, 19}, - "bvwbjplbgvbhsrlpgdmjqwftvncz": {5, 23}, - "nppdvjthqldpwncqszvftbrmjlhg": {6, 23}, - "nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg": {10, 29}, - "zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw": {11, 26}, -} - -//go:embed input.txt -var fullInput string - -func Run(useSampleInput bool) error { - for input, expectedResult := range knownInputs { - result, err := detectMarker(input, startOfPacket) - if err != nil { - return fmt.Errorf("tests failed: %w", err) - } - if result != expectedResult.packet { - return fmt.Errorf("unexpected start-of-packet marker for %q: Expected %d, got %d", input, expectedResult.packet, result) - } - result, err = detectMarker(input, startOfMessage) - if err != nil { - return fmt.Errorf("tests failed: %w", err) - } - if result != expectedResult.message { - return fmt.Errorf("unexpected start-of-message marker for %q: Expected %d, got %d", input, expectedResult.message, result) - } - } - if useSampleInput { - return nil - } - - index, err := detectMarker(fullInput, startOfPacket) - if err != nil { - return fmt.Errorf("failed to detect start-of-packet marker: %w", err) - } - fmt.Printf("start-of-packet marker after %d\n", index) - - index, err = detectMarker(fullInput, startOfMessage) - if err != nil { - return fmt.Errorf("failed to detect start-of-message marker: %w", err) - } - fmt.Printf("start-of-message marker after %d\n", index) - - return nil -} - -func isMarker(s string) bool { - for i := 0; i < len(s); i++ { - for j := 0; j < i; j++ { - if s[j] == s[i] { - return false - } - } - } - return true -} - -func detectMarker(input string, t requiredLength) (int, error) { - for i := int(t); i < len(input); i++ { - if isMarker(input[i-int(t):i]) { - return i, nil - } - } - return -1, fmt.Errorf("cannot find marker") -} diff --git a/days/6/input.txt b/days/6/input.txt deleted file mode 100644 index 51e21b2..0000000 --- a/days/6/input.txt +++ /dev/null @@ -1 +0,0 @@ -bfdbbngnvnsvshhhrvrbrtbrrhqrqgrrmmdfmmqttptltntrntrnrcrdcrrctctdtwtrwwmlltcltcllmpprvvtbbmbvbsvvqwvvscswsqqgzqqppvzppnddjwddlrdlllmwllfccdfccswwrhhndhdhfdftdfdcdcllcjjbsbgssvlvrrhfrfjfpjffvnfvfwfzftztwwrhwrhwhwddpjjmhmgmsssstzszqzfqzzprpzpnndttphtpphvvcpcjppdtdwwqgwwwnhwnnvhvsvqqtrrbsscwssgwglgwlldjdzjjbsjbsbvvpbvppvfvqvbqbzzwtwbwpbbbcffdgggpnpfptpfphfhfthfthffzrrbzbcblbmmzmhhnvvqvlvwvzvtztgzznbbcqbccwhcwcnwnhndhhgcghhlthllplvppgngrgsswfsfnfjjswstsrtrhthhqzqggdtggzvvjljddqdzzrmrjmjcmjmrrwlldttrhhfjjgbglgjlldrllppnwpnwnndrddtdqdhhpccbgcgzzswzztgzzrwwzzmtztvvrtrgttvddwvwvmwvmmdjdrdtthqhgqhggldgdfdnnzjnjffmrrnprnpnssjrrbrjjrrzvrvhvllfvlvnlvvhlhrhzrzrsrswrssjvjdjfjwwjmjvjjthhnjnmnppsccmlcclfclcbllldwldwdlwddbddmnmrmgrmmtsszgssqjsqscswwzmwmbwwvqqbtbtwwpbbwdbdbhhqmqgqddflfmfnmffbtfbbsdsffspsjpsspzszccrsrstrtjrjppcrrpqqvttsbbjtbjjpbbccmzznvvzzvnvmmwmhmvmsstlssqtssvggtbgttgvtggfhggbcgcmcrmcmhhbttdlttfrfprrvttrtggcpplccqggcwwdjjjplprrbsrbbjsjbbfhbhphtttpffdgdgjddzldzlzplpnplljttdqqlmlllhzhjhccpwcwhwwbbqtqffjpfpfpjptplltbtzbbwwvggpcpprdprpbpvvgzgczzfffzcfzccjffrmrhmrhhchvhddsvswscsnnpfppdrdcrdrgdgmdgmgllhggjwggvqvmmvrrzpprhhqfhfvffvlvnlngnffbbtccfbfhfwhhhhwcwzwjjbffvrffqrrnsnwswrsrvrjvrvprpsptspttbztzfzlfzlflcflclqlplglmlqqvlvvhccmmddqvqzvvmlllvnlnhnfnwnlndnntrrhvvgjjnpnggfqgqdqqzvvclvclvlfvlvvlzlssqffmrfmfmjjczcmmmnttnfnmfnmmmhmggjgdjjqmjjvsslszlzrrpdpcpfcpfpnpssvtsvtvllbttzzljzzhrrnsnddjgdjgjljzzvhvddmdvvdtdmmpmqmnnwcwfwbfwwsvvbpvvgvnvcvdvtvrrcppwbppcqpccwqqzmqmmzczppwbbrzrjzzcrcvrrpttrjjcdjcjfcclscstthqhfqhffdcfdfqdqldddsswbblppdmdnnjvvhwvhvjhvjhjhlhcclrrcqcgcjgcjjtbtctbcbsccfwwltlrlplpfpjphplhhgtghhrppwhhrprwpwhhdqdpdwpwwtccvncvvvrpvphpssfpplcczttltgltldlmlqmmbsszdszznpprsprsprsppsbppjddjhhnrrfsrffmlmglgmlglccddpssdpsddhhfmfsfrfsfnnlggfrgghmgmrmprmprrnvrnnbqnqddhhfwfmfwfmfpfdfzdzppsbpsbpprfrvvwvtwtltvlttrhhgvhhjttmssdggnzzvmvcczmzbzwzttvtpvpcphcctmmhshjsjbssglsglgtltslscchhhsjjpljjdtdsdpppptlpprmppwdppglgmggnddztdzddzppswwmhfbpqzffjqgmsntwsnrwqrqwgpwgrbpbjwrhbcdcvqjnwslsnwhglcsjbwjhswjvzssfqgwbbdgbwfrblfmmlmsndhtlbwzfwsspqlncspqbgbnzshbwpvrmjqjzbcbzzdgssbtqdzffjphqjvrspfrjhpspbwcjwbfhqzsdnjwqjzjtjgnbrdbwqhzffphzppvlmsmppqcfjbjbdsnbwtvthwqcfrtfrwchnmqmhnwfcjtbwqwwvlnpmwlrvzwljrljzqstzglqwbzfdftzltlcbvmmfwcjqglvznztwnvzvftpndqmngqswppsnqhdbgthrddfbcfpflpndrhmcqwvnbfztsvnjjdwqgpmvdwvdftgbtvrwbnvvrwsdfzhwbwdhlpzbcqdzhbfqtpjqcmrpvcsrmcwvgghqrclfzpfgnppzmhvdhvdfrcrnjbdcwbftcqjhhfdsnfnwjzjllzzqftzsjrqnsbpjdcswhhmwwdzmvmqcjtqnczjcvzmmqwzjhjpcczgpbmcvbwmpmvnghlrgcmrrdnmjvmvnhtpfpgwgmdfzvlbclzjzwdqqcvfhhgfzdhzpdvfmwjlzzrpdgzmttmvvcplbwfzqftcgcwcgcpgwvnmlqsplpqwfnhwvqtlwcspqdzshsqnlcpqhpcpbwdhdjsmvtbqdwbcrscqfjcrcjhbjbpzbshpbmlcthmbjfwhzfphgbfqfnfztptzvdnwrpslmdtpmzmpbsszqshwdghrbtvhwzhcmpcgfqggpgzwmhhdrlhlvnpzvwwhzqvgvhrzngttcnqgjjhnblncnqnjzlwnmwnrtvwjtnrbhthncwmzwqdbdgtwrncljddnbhmphgjzfrrgmmcwfwjwjlcrhvcdtvsrvsfhmlgmzsgjchhrfmqslmdgtdtrlbhdffddvbsdbdwlwdcmcmmpvzpdtmbthjdzlpwftptpfsggmhjfjwvbwljsfhfwtbfwmczwhbmhvzllqtcqqfbrcdqqsrcpfmnswnfzfqghcmcbqwgvzqpwvvmbpddlhgjgzvgmpljznrhqphwcztqzpnhzqdgpwwclmsgpwnwtvtsjsdmcnvmjbqglttrhbzqdbgwnbsqzmsmztndrtmlpszhzgjbbftbsdwwdrlftrbbnrsqshfhdpdrwmztcqzdjlnthnjhppwntmbqdgzpmfmfnccblsdwljqhjfgtlgvpzpjbsndmwzfwrbmdhpnmbchqlwqtbhhhqqbsfnvscjwrzvjdtvbsqwzvfhwbbjgqpzcwqjdrlfmggzmhbcrhtbqdjntbtqdvmvpqflmccfpnbmnmtqbdflsgczpbsqpfphlzqgvwbjlmsgshrhpcljzdvwvdvlqqwchtjmjgtqjhgwtnddmhphwhvwhtrhfbjjjzfgrcqngnnddctzdzlqjlbdwmjqzccwrvctrzgtzqsswggbqdnplclhtdslcvzhppcjjslnshtwjnbrwdprqhdtfqmqpgfgnqtdnnhrnzfrsqhlftpdslgmmvqhvpjqjwpwgtnmgrbhwntdjftfwtjzjtprctbtsjmqmpcbbtrjvsgqgsfjprqmsmdztbhnbgzldqfzgwqwnnccgcfclctrwqmqpgvfglgsmmpjszqnphnzcnvswpsfsrmnsnlqnpmvfdvdtfgzrdmbftdrrrbfsvzfgmnffvjpcpnndrwhtjjrrvnztlfhcvfqjgfrhtbnhmwnrmwdhzmmtvjmsqmghtbtfjwdnvdcqtqjrfhrwscjftmbgjmcsrbpdpttlmvfmnfjhnptqvggnshzqnlqqdpqqsqssppbwpblhgfrwrblpzwvqphpsgfmbpqtqqpjpgnbblzstgcjhqntgpbfwlzzctqbnbvpgwsdsdldqzhvznqcsrrghpwllshqpdlqnqgzfwrnhwsvhftzplspcbqmclplprlthvwjhdndrjblqdgwvgjlbmblbmcnbzwzdlnpnhhppvrtngvqqwsttgwlvtcqmtrvpbnvcnfqdtqrsrsmhclmtgbdwwdvhwgfcqpmprcpdhqwftcchbwvstcdqrlwtgbcfqfgzprgvpbbzlqfzbqtcrlzscnqpqwtgzbbbdvsvmhggdr diff --git a/days/7/day7.go b/days/7/day7.go deleted file mode 100644 index fefe94e..0000000 --- a/days/7/day7.go +++ /dev/null @@ -1,225 +0,0 @@ -package _7 - -import ( - _ "embed" - "fmt" - "strconv" - "strings" - - "github.com/ankon/adventofcode/2022/days" -) - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -const totalDiskSpace = 70000000 -const requiredUnusedDiskSpace = 30000000 - -type ftype int32 - -const ( - file ftype = iota - dir -) - -type direntry struct { - ftype ftype - size int - name string - - children []direntry - parent *direntry -} - -func readDir(parent *direntry, lines []string) ([]direntry, int, error) { - entries := []direntry{} - i := 0 - for i = 0; i < len(lines); i++ { - if lines[i] == "" { - break - } - - s, name, found := strings.Cut(lines[i], " ") - if !found { - return []direntry{}, -1, fmt.Errorf("invalid ls output %q", lines[i]) - } - if s == "$" { - break - } - - var ftype ftype - var size int - if s == "dir" { - ftype = dir - } else { - ftype = file - tmp, err := strconv.Atoi(s) - if err != nil { - return []direntry{}, -1, err - } - size = tmp - } - entries = append(entries, direntry{ - ftype, - size, - name, - []direntry{}, - parent, - }) - } - - return entries, i, nil -} - -func loadFS(input string) (root direntry, err error) { - root = direntry{ - ftype: dir, - size: 0, - name: "/", - children: []direntry{}, - } - cwd := &root - lines := strings.Split(input, "\n") - for i := 0; i < len(lines); i++ { - cmd := lines[i] - if cmd == "" { - continue - } - - p := strings.Split(cmd, " ") - if p[0] != "$" { - return direntry{}, fmt.Errorf("command expected") - } - - switch p[1] { - case "cd": - name := p[2] - if name == "/" { - cwd = &root - } else if name == ".." { - cwd = cwd.parent - } else { - var ncwd *direntry - for i := 0; i < len(cwd.children); i++ { - if cwd.children[i].name == name { - ncwd = &cwd.children[i] - break - } - } - if ncwd == nil { - return direntry{}, fmt.Errorf("no such directory %q", name) - } - cwd = ncwd - } - case "ls": - entries, count, err := readDir(cwd, lines[i+1:]) - if err != nil { - return direntry{}, err - } - cwd.children = append(cwd.children, entries...) - i += count - default: - return direntry{}, fmt.Errorf("unknown command %q", p[0]) - } - } - - return root, nil -} - -func printDir(de *direntry, indent int) { - fmt.Printf("%*s- %s\n", indent, "", de.name) - for _, child := range de.children { - switch child.ftype { - case dir: - printDir(&child, indent+2) - case file: - fmt.Printf("%*s- %s (size=%d)\n", indent+2, "", child.name, child.size) - default: - panic("huh?") - } - } -} - -func calculateDirSizes(de *direntry) int { - size := 0 - for i := 0; i < len(de.children); i++ { - child := &de.children[i] - if child.ftype == dir { - size += calculateDirSizes(child) - } else { - size += child.size - } - } - de.size = size - return size -} - -func findSumOfDirsWithSizeLessThan100K(de *direntry) int { - result := 0 - - for i := 0; i < len(de.children); i++ { - child := &de.children[i] - if child.ftype == file { - continue - } - - if child.size < 100000 { - result += child.size - } - result += findSumOfDirsWithSizeLessThan100K(child) - } - return result -} - -func findSmallestDirectoryWithSizeLargerThan(de *direntry, minSize int) *direntry { - var result *direntry - for i := 0; i < len(de.children); i++ { - child := &de.children[i] - if child.ftype == file { - continue - } - if child.size < minSize { - // Too small, and won't get bigger - continue - } - - // This directory might work, see whether we can just - // delete a part of it. - better := findSmallestDirectoryWithSizeLargerThan(child, minSize) - if better == nil { - // Nope, the whole thing needs to go. - better = child - } - if result == nil || result.size > better.size { - result = better - } - } - return result -} - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - root, err := loadFS(input) - if err != nil { - return err - } - printDir(&root, 0) - - totalSize := calculateDirSizes(&root) - fmt.Printf("total size %d\n", totalSize) - - sum := findSumOfDirsWithSizeLessThan100K(&root) - fmt.Printf("sum of sizes of dirs < 100000: %d\n", sum) - - requiredCleanupSize := requiredUnusedDiskSpace - (totalDiskSpace - totalSize) - toDelete := findSmallestDirectoryWithSizeLargerThan(&root, requiredCleanupSize) - if toDelete == nil { - return fmt.Errorf("cannot find directory to delete to free up %d", requiredCleanupSize) - } - fmt.Printf("delete %q, frees up %d\n", toDelete.name, toDelete.size) - - return nil -} diff --git a/days/7/input.txt b/days/7/input.txt deleted file mode 100644 index 3c46e58..0000000 --- a/days/7/input.txt +++ /dev/null @@ -1,1046 +0,0 @@ -$ cd / -$ ls -149291 cgc.vzv -dir cmcrzdt -dir hwdvrrp -26925 hwqvsl -dir lsmv -dir ngfllcq -dir ngnzzmpc -dir pwhjps -dir rgwnzttf -260556 tcglclw.hsn -dir trvznjhb -dir wgcqrc -68873 whpnhm -$ cd cmcrzdt -$ ls -dir chqllfw -95243 hjpf -108868 hwqvsl -115004 jpppczvz.mtp -dir lnsgfnbr -dir pdtjlb -dir rqfzvwts -dir trvznjhb -$ cd chqllfw -$ ls -56623 cgs.hbt -134804 zqb.grc -$ cd .. -$ cd lnsgfnbr -$ ls -dir jtzw -dir ngfllcq -dir sdm -dir wlsg -$ cd jtzw -$ ls -dir nfz -$ cd nfz -$ ls -255427 hwqvsl -94147 tmnjbqq.fzh -$ cd .. -$ cd .. -$ cd ngfllcq -$ ls -110661 cdgqtwcv.lzn -208050 dpf -$ cd .. -$ cd sdm -$ ls -dir dhwm -dir ngfllcq -125983 rfdz.vqm -24227 tzn -41909 tzn.vnr -dir zdzq -$ cd dhwm -$ ls -dir clr -dir lhv -dir ncvmgn -212499 ngfllcq.dcr -191108 nggnj -dir pdtjlb -dir pwhjps -dir sqqbthdp -dir trvznjhb -$ cd clr -$ ls -dir lnbc -87079 npwhncc -109530 pfqhpr.tzl -249566 tmnjbqq.fzh -dir zgmgztcd -$ cd lnbc -$ ls -62635 ftshngp.vbj -$ cd .. -$ cd zgmgztcd -$ ls -149111 pwhjps.fjm -$ cd .. -$ cd .. -$ cd lhv -$ ls -dir phzfwl -$ cd phzfwl -$ ls -dir gmzcjzm -$ cd gmzcjzm -$ ls -263161 vsptqdv -$ cd .. -$ cd .. -$ cd .. -$ cd ncvmgn -$ ls -245840 hjpf -21272 pbcjtbg -dir stm -$ cd stm -$ ls -dir hnbrd -$ cd hnbrd -$ ls -102906 lftjtq.gdt -45082 vsptqdv -$ cd .. -$ cd .. -$ cd .. -$ cd pdtjlb -$ ls -171382 hwqvsl -$ cd .. -$ cd pwhjps -$ ls -75342 cgc.vzv -185458 hwqvsl -254359 ngfllcq.jzd -dir pdtjlb -200999 slnlws.sgh -91174 vqqbcb -dir zmc -$ cd pdtjlb -$ ls -39001 ngfllcq -$ cd .. -$ cd zmc -$ ls -dir cjqmc -$ cd cjqmc -$ ls -257668 ctsfdprp -889 mzr.hnp -$ cd .. -$ cd .. -$ cd .. -$ cd sqqbthdp -$ ls -154217 pwhjps.jtn -$ cd .. -$ cd trvznjhb -$ ls -105431 hwqvsl -$ cd .. -$ cd .. -$ cd ngfllcq -$ ls -183850 dcppzj.lmm -131039 hbpn.zlp -110398 hjpf -dir pwhjps -251784 rqgslj.sqg -dir szqf -150728 vsptqdv -$ cd pwhjps -$ ls -dir pzrtwv -156616 rpbh.ftj -dir tzn -$ cd pzrtwv -$ ls -197890 tzn -$ cd .. -$ cd tzn -$ ls -121296 pdtjlb.nmg -$ cd .. -$ cd .. -$ cd szqf -$ ls -dir ngfllcq -dir qtrhn -$ cd ngfllcq -$ ls -dir vnfcczg -$ cd vnfcczg -$ ls -86691 cgc.vzv -189290 hjds.lwf -230265 hwqvsl -dir jbmvmzn -223129 ngfllcq.mdw -dir rpcbpjvm -215119 tmnjbqq.fzh -$ cd jbmvmzn -$ ls -dir flrszsrr -175047 hjpf -dir jrzf -dir ngfllcq -$ cd flrszsrr -$ ls -163007 zdvfmqr.pfq -$ cd .. -$ cd jrzf -$ ls -32641 qbnz -$ cd .. -$ cd ngfllcq -$ ls -dir dlcvcd -dir gcpftfm -183962 tzn.mjh -$ cd dlcvcd -$ ls -260612 mhf -$ cd .. -$ cd gcpftfm -$ ls -227489 hwqvsl -$ cd .. -$ cd .. -$ cd .. -$ cd rpcbpjvm -$ ls -dir tnwzgrvw -$ cd tnwzgrvw -$ ls -dir trvznjhb -$ cd trvznjhb -$ ls -127767 pdtjlb.qjw -$ cd .. -$ cd .. -$ cd .. -$ cd .. -$ cd .. -$ cd qtrhn -$ ls -81716 dngdll -76367 tdj -180116 tmnjbqq.fzh -$ cd .. -$ cd .. -$ cd .. -$ cd zdzq -$ ls -192339 bqcmzm.vzw -dir cplvj -dir drpmlmf -92165 mcthl.dzw -dir qccnln -$ cd cplvj -$ ls -dir gmqddf -71720 hjpf -220700 hwqvsl -260353 lgw.msr -$ cd gmqddf -$ ls -36587 dmdgjrs -$ cd .. -$ cd .. -$ cd drpmlmf -$ ls -4896 hjpf -dir ngfllcq -65712 pwhjps.mng -67097 tmnjbqq.fzh -$ cd ngfllcq -$ ls -248967 swvf.prt -$ cd .. -$ cd .. -$ cd qccnln -$ ls -dir tzn -$ cd tzn -$ ls -81833 vsptqdv -$ cd .. -$ cd .. -$ cd .. -$ cd .. -$ cd wlsg -$ ls -181214 nmglzcds.hcg -195698 pdtjlb.vbr -dir trvznjhb -77162 vsptqdv -$ cd trvznjhb -$ ls -237856 trvznjhb -$ cd .. -$ cd .. -$ cd .. -$ cd pdtjlb -$ ls -101237 hwqvsl -dir jssl -dir ngfllcq -dir pvlqvdrw -dir pwhjps -dir tzn -115255 vsptqdv -$ cd jssl -$ ls -76335 smmjjrp -$ cd .. -$ cd ngfllcq -$ ls -102639 cgc.vzv -55243 fjfhdtr.ltc -$ cd .. -$ cd pvlqvdrw -$ ls -38570 pwhjps.qgq -191322 scnbjgg.gww -$ cd .. -$ cd pwhjps -$ ls -dir ghfwwj -dir vtr -$ cd ghfwwj -$ ls -109461 mdtp.ztw -$ cd .. -$ cd vtr -$ ls -dir fmtpdc -$ cd fmtpdc -$ ls -42101 bcdbqcs.lhp -$ cd .. -$ cd .. -$ cd .. -$ cd tzn -$ ls -dir pdtjlb -$ cd pdtjlb -$ ls -154813 vsptqdv -$ cd .. -$ cd .. -$ cd .. -$ cd rqfzvwts -$ ls -250112 hwqvsl -63241 tzn -149460 tzn.pph -$ cd .. -$ cd trvznjhb -$ ls -784 bdptcbl.ntt -108339 cgc.vzv -dir hnpdrdsm -dir mnnwcmd -dir ngfllcq -dir pbsnd -dir pdtjlb -261083 rhl.cjh -dir trvznjhb -103421 wjftfs -$ cd hnpdrdsm -$ ls -253895 pwhjps.nps -36928 ssjhl -235679 tmnjbqq.fzh -38049 trvznjhb.dzs -$ cd .. -$ cd mnnwcmd -$ ls -218411 fvzhntq.rwm -78694 gwlcbbtm -243270 hjpf -15610 trvznjhb.wdj -$ cd .. -$ cd ngfllcq -$ ls -dir fmhlq -dir fwbdttbj -dir hccstwh -$ cd fmhlq -$ ls -142240 rbrwv.hjl -dir tjpwvb -256604 tmnjbqq.fzh -dir trvznjhb -$ cd tjpwvb -$ ls -83436 sfrpt -$ cd .. -$ cd trvznjhb -$ ls -44433 trvznjhb -$ cd .. -$ cd .. -$ cd fwbdttbj -$ ls -4127 hwqvsl -$ cd .. -$ cd hccstwh -$ ls -dir cbd -243765 lvzsrqlw.llc -$ cd cbd -$ ls -158372 vzgtjqbd.tmd -$ cd .. -$ cd .. -$ cd .. -$ cd pbsnd -$ ls -172548 cgc.vzv -261836 pwhjps -$ cd .. -$ cd pdtjlb -$ ls -73184 cgc.vzv -dir mdbjwvh -dir mgt -dir nbrvvghc -98702 ngf.gtb -dir ngfllcq -224788 pdtjlb -191754 tmnjbqq.fzh -189444 tnqwbmzm.vlq -dir tzn -dir ztzsg -$ cd mdbjwvh -$ ls -135602 nvt.rjh -$ cd .. -$ cd mgt -$ ls -dir pbrtf -dir whflvwv -$ cd pbrtf -$ ls -dir tnnnllg -$ cd tnnnllg -$ ls -269436 hjpf -$ cd .. -$ cd .. -$ cd whflvwv -$ ls -185562 ngfllcq -dir rdl -150984 trvznjhb -$ cd rdl -$ ls -231952 mqjcttf -$ cd .. -$ cd .. -$ cd .. -$ cd nbrvvghc -$ ls -dir pdtjlb -$ cd pdtjlb -$ ls -40347 hjpf -dir vwl -$ cd vwl -$ ls -124408 tzn.hjw -$ cd .. -$ cd .. -$ cd .. -$ cd ngfllcq -$ ls -54894 bvgf -$ cd .. -$ cd tzn -$ ls -41506 vnhlvqqw.cvd -$ cd .. -$ cd ztzsg -$ ls -216433 fzsnpr.vrd -dir grrngq -dir hcmvbhp -dir lbmnq -19985 ngfllcq -dir pqqjgbvj -dir zsnggz -$ cd grrngq -$ ls -dir cqcvb -dir ngfllcq -dir shrhb -$ cd cqcvb -$ ls -125712 cgc.vzv -69800 fpszwd -160009 rbbwsszz -dir trvznjhb -33640 tzghd.fjp -$ cd trvznjhb -$ ls -dir gtjfll -dir mrncfvnp -dir pwt -dir trvznjhb -173974 tzn -$ cd gtjfll -$ ls -126840 cgc.vzv -180163 fswwvhwn -dir gnpcbvmt -122192 ngfllcq.snb -$ cd gnpcbvmt -$ ls -127188 crhvwb.pct -218972 mwg -$ cd .. -$ cd .. -$ cd mrncfvnp -$ ls -216569 phlbdl -$ cd .. -$ cd pwt -$ ls -119692 tmnjbqq.fzh -$ cd .. -$ cd trvznjhb -$ ls -203464 nltqsvd.fhc -$ cd .. -$ cd .. -$ cd .. -$ cd ngfllcq -$ ls -31226 rdwczp.hfq -$ cd .. -$ cd shrhb -$ ls -246035 bnbg -98513 hjpf -$ cd .. -$ cd .. -$ cd hcmvbhp -$ ls -dir cbb -201230 cgc.vzv -dir grmmpz -220707 hjpf -dir jnr -dir psv -dir trvznjhb -134184 trvznjhb.ghp -228507 vsptqdv -$ cd cbb -$ ls -17897 hwqvsl -$ cd .. -$ cd grmmpz -$ ls -214171 spsnch.drs -$ cd .. -$ cd jnr -$ ls -82130 bhjqplbc.rth -$ cd .. -$ cd psv -$ ls -215898 pwhjps -$ cd .. -$ cd trvznjhb -$ ls -dir dfcn -98111 gwt.fmw -20948 hjpf -dir pwhjps -dir rnlrgd -$ cd dfcn -$ ls -dir fqm -179114 mbcrjb -dir trvznjhb -dir vfrrzdb -$ cd fqm -$ ls -dir frgwsrdh -$ cd frgwsrdh -$ ls -142027 hhpwsl -$ cd .. -$ cd .. -$ cd trvznjhb -$ ls -dir nbbb -34253 ngfllcq.src -dir qgqmmvg -dir tfgwmlc -11919 trvznjhb.qgz -dir tzn -24383 zvfzhb.dcw -$ cd nbbb -$ ls -260947 pwhjps.bdq -$ cd .. -$ cd qgqmmvg -$ ls -67028 wjvhq.tdz -$ cd .. -$ cd tfgwmlc -$ ls -dir rmcgqpb -dir wdtmdtz -$ cd rmcgqpb -$ ls -263786 nsmcndc.bjs -$ cd .. -$ cd wdtmdtz -$ ls -37751 lnspfqv.tpp -$ cd .. -$ cd .. -$ cd tzn -$ ls -265035 nqsgm.dhm -$ cd .. -$ cd .. -$ cd vfrrzdb -$ ls -dir pzbtsnd -dir srpdb -$ cd pzbtsnd -$ ls -72770 pdtjlb -$ cd .. -$ cd srpdb -$ ls -231540 dzgsf -dir ngfllcq -dir sjv -$ cd ngfllcq -$ ls -26488 cgc.vzv -195815 dfjss -119177 lbjtjqr -$ cd .. -$ cd sjv -$ ls -225677 msgjj -228113 ngfllcq -92448 tzn.rbp -$ cd .. -$ cd .. -$ cd .. -$ cd .. -$ cd pwhjps -$ ls -171613 nzqd.rzh -$ cd .. -$ cd rnlrgd -$ ls -132964 hjpf -146636 hwqvsl -187596 mlrllbbb.wmh -92535 trvznjhb -$ cd .. -$ cd .. -$ cd .. -$ cd lbmnq -$ ls -142963 qfpjgvll.ncb -$ cd .. -$ cd pqqjgbvj -$ ls -dir dfhhzwp -253570 jjbr.cgf -dir lchljrwb -dir pdtjlb -$ cd dfhhzwp -$ ls -dir bqp -$ cd bqp -$ ls -122939 hjpf -$ cd .. -$ cd .. -$ cd lchljrwb -$ ls -259475 fqmppdtd.tjm -$ cd .. -$ cd pdtjlb -$ ls -199658 vsptqdv -$ cd .. -$ cd .. -$ cd zsnggz -$ ls -117242 hjpf -$ cd .. -$ cd .. -$ cd .. -$ cd trvznjhb -$ ls -dir bgvqct -160709 dtq -dir fldlwj -dir ndq -221408 tmnjbqq.fzh -69148 zvfzt.rjm -$ cd bgvqct -$ ls -66024 cmjrmfn.lpt -40153 fdlvqgn.dbt -135848 tmnjbqq.fzh -$ cd .. -$ cd fldlwj -$ ls -172275 ngfllcq.gbb -$ cd .. -$ cd ndq -$ ls -117311 bbhlcn.qll -dir dtzmzgw -123263 hsb -dir jnthg -111208 pdtjlb -200860 pjq -$ cd dtzmzgw -$ ls -dir tzn -$ cd tzn -$ ls -249561 pszf.zcn -$ cd .. -$ cd .. -$ cd jnthg -$ ls -17013 pwhjps.gpp -$ cd .. -$ cd .. -$ cd .. -$ cd .. -$ cd .. -$ cd hwdvrrp -$ ls -dir fgvqft -dir fwc -dir sfhsb -dir tzn -dir wbtf -$ cd fgvqft -$ ls -215710 wzh -$ cd .. -$ cd fwc -$ ls -184576 dmvqc.tsr -dir hgznwf -dir lfjtqz -dir ngfllcq -53748 ngfllcq.vgl -dir pgpvcp -$ cd hgznwf -$ ls -51012 tmnjbqq.fzh -$ cd .. -$ cd lfjtqz -$ ls -96666 fwttv.qrp -203264 nhc.lgd -dir pwhjps -213570 tzn -$ cd pwhjps -$ ls -69941 frqq.jnv -136814 pqmsc.dgz -185821 rww.trv -$ cd .. -$ cd .. -$ cd ngfllcq -$ ls -97361 zcw.zrq -$ cd .. -$ cd pgpvcp -$ ls -834 nwv.mtw -$ cd .. -$ cd .. -$ cd sfhsb -$ ls -78513 pdtjlb -$ cd .. -$ cd tzn -$ ls -dir lpf -$ cd lpf -$ ls -242317 bngfvvgq.ptp -82304 ngfllcq.qdz -dir wsvqtcb -$ cd wsvqtcb -$ ls -32176 vrwlnphn.nnv -$ cd .. -$ cd .. -$ cd .. -$ cd wbtf -$ ls -53446 jvvdpn -41661 ngfllcq.vhl -dir pwhjps -231151 tzn -241080 vdzdhdtb.dgj -dir vlqmz -$ cd pwhjps -$ ls -200296 hdds.lsw -$ cd .. -$ cd vlqmz -$ ls -166538 pwhjps.mnq -$ cd .. -$ cd .. -$ cd .. -$ cd lsmv -$ ls -dir dtjjv -87897 hjpf -216417 hwqvsl -dir ngfllcq -dir pdtjlb -dir qlnlbcdv -230724 vsptqdv -177119 vvzvnn -$ cd dtjjv -$ ls -218742 hjpf -$ cd .. -$ cd ngfllcq -$ ls -38560 cgc.vzv -257037 fbttg.jlc -29948 pwhjps.bvj -1253 trvznjhb.nzl -241388 tzn.vdb -dir wlmtj -$ cd wlmtj -$ ls -51957 hjpf -27480 pwhjps.hgj -dir qdjfgz -dir shb -182077 tclmtwh.wzr -dir trvznjhb -103119 twlf.rnl -31950 tzn.zfm -$ cd qdjfgz -$ ls -238882 hpms.gll -dir qpbsmmp -184633 trvznjhb.nsb -130374 vsptqdv -$ cd qpbsmmp -$ ls -60269 spsbz -$ cd .. -$ cd .. -$ cd shb -$ ls -140111 vsptqdv -$ cd .. -$ cd trvznjhb -$ ls -dir qjqzppj -$ cd qjqzppj -$ ls -203246 hjpf -$ cd .. -$ cd .. -$ cd .. -$ cd .. -$ cd pdtjlb -$ ls -41982 hjpf -245930 hwqvsl -dir mmnhtmr -42314 ngfllcq.tcn -68269 pdtjlb -103066 vhtjp.grt -$ cd mmnhtmr -$ ls -dir zqjjgvj -$ cd zqjjgvj -$ ls -263209 nvhflpng.ngd -$ cd .. -$ cd .. -$ cd .. -$ cd qlnlbcdv -$ ls -dir jmd -58921 pdtjlb.mwb -dir pzjgmm -dir qqvrvcw -79958 rrqmn.zwv -18158 swjpt.trv -dir trvznjhb -dir tzn -92135 zjb.nns -268795 zspzsb.szp -$ cd jmd -$ ls -137766 pwhjps -$ cd .. -$ cd pzjgmm -$ ls -1704 tzn.rhf -66307 tzn.zll -116623 vrfvctv.clb -$ cd .. -$ cd qqvrvcw -$ ls -179302 zrqf.fcn -$ cd .. -$ cd trvznjhb -$ ls -265026 qfzlgccf.hvz -dir rbbmmcc -$ cd rbbmmcc -$ ls -dir rtr -$ cd rtr -$ ls -dir dtw -$ cd dtw -$ ls -249472 svs.tgj -$ cd .. -$ cd .. -$ cd .. -$ cd .. -$ cd tzn -$ ls -80112 pdtjlb.thm -$ cd .. -$ cd .. -$ cd .. -$ cd ngfllcq -$ ls -228868 ggcfwgr.mwh -10205 gztwg.pwz -136188 hjpf -141381 hwqvsl -250522 pdtjlb.dwg -dir pwhjps -dir qcwvfl -dir tzn -dir zgwcwqr -$ cd pwhjps -$ ls -19881 tmrljtw -$ cd .. -$ cd qcwvfl -$ ls -63317 fcjsw.jcj -dir gvvfsq -272464 lvqc -148216 nwppjnwc.sdg -121107 tzn.ppw -dir vwfb -$ cd gvvfsq -$ ls -80607 jplds.mjz -$ cd .. -$ cd vwfb -$ ls -dir gtlfdvjz -$ cd gtlfdvjz -$ ls -228623 jbbplpz -dir shf -$ cd shf -$ ls -120966 cgc.vzv -$ cd .. -$ cd .. -$ cd .. -$ cd .. -$ cd tzn -$ ls -215528 cgc.vzv -112331 gtzcl.rzp -128653 mqd.dcz -dir ngfllcq -dir vmfgbzmw -$ cd ngfllcq -$ ls -207193 qchb.hmv -$ cd .. -$ cd vmfgbzmw -$ ls -16152 vtlgffn -$ cd .. -$ cd .. -$ cd zgwcwqr -$ ls -dir pdtjlb -110033 vsptqdv -$ cd pdtjlb -$ ls -9746 cgc.vzv -8010 jdvjpps -$ cd .. -$ cd .. -$ cd .. -$ cd ngnzzmpc -$ ls -116647 gmsnm -157873 hwqvsl -$ cd .. -$ cd pwhjps -$ ls -96321 cgc.vzv -dir lcds -dir tzn -$ cd lcds -$ ls -134975 wcfv.gpd -$ cd .. -$ cd tzn -$ ls -95149 hjpf -55950 pwhjps.rpq -166540 tdt.pgw -236704 trvznjhb.ccn -$ cd .. -$ cd .. -$ cd rgwnzttf -$ ls -122721 hjpf -$ cd .. -$ cd trvznjhb -$ ls -106424 zvqz -$ cd .. -$ cd wgcqrc -$ ls -87367 hjpf -63133 lld -234148 pwhjps.lcr -dir rjnnz -19538 tzn -233765 zlvznnwj -$ cd rjnnz -$ ls -258856 gpgdm diff --git a/days/7/sample.txt b/days/7/sample.txt deleted file mode 100644 index 09a921e..0000000 --- a/days/7/sample.txt +++ /dev/null @@ -1,23 +0,0 @@ -$ cd / -$ ls -dir a -14848514 b.txt -8504156 c.dat -dir d -$ cd a -$ ls -dir e -29116 f -2557 g -62596 h.lst -$ cd e -$ ls -584 i -$ cd .. -$ cd .. -$ cd d -$ ls -4060174 j -8033020 d.log -5626152 d.ext -7214296 k diff --git a/days/8/day8.go b/days/8/day8.go deleted file mode 100644 index da72992..0000000 --- a/days/8/day8.go +++ /dev/null @@ -1,113 +0,0 @@ -package _8 - -import ( - _ "embed" - "fmt" - "strings" - - "github.com/ankon/adventofcode/2022/days" -) - -//go:embed sample.txt -var sampleInput string - -//go:embed input.txt -var fullInput string - -type trees [][]byte - -type direction struct { - dx, dy int -} - -var directions = []direction{ - {0, -1}, - {1, 0}, - {0, 1}, - {-1, 0}, -} - -func visibilityInDirection(trees trees, x, y int, d direction) (int, bool) { - height := len(trees) - width := len(trees[0]) - - result := 0 - t := trees[y][x] - x += d.dx - y += d.dy - for x >= 0 && x < width && y >= 0 && y < height { - result++ - if trees[y][x] >= t { - return result, false - } - x += d.dx - y += d.dy - } - return result, true -} - -func isVisibleFromOutside(trees trees, x, y int) bool { - for _, d := range directions { - if _, visibleFromOutside := visibilityInDirection(trees, x, y, d); visibleFromOutside { - return true - } - } - return false -} - -func calculateScenicScore(trees trees, x, y int) int { - result := 1 - for _, d := range directions { - distance, _ := visibilityInDirection(trees, x, y, d) - result *= distance - } - return result -} - -func printScenicScoreMap(scenicScoreMap [][]int) { - for y := 0; y < len(scenicScoreMap); y++ { - s := "" - for x := 0; x < len(scenicScoreMap[y]); x++ { - s += fmt.Sprintf("%4d ", scenicScoreMap[y][x]) - } - fmt.Println(s) - } -} - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - lines := strings.Split(strings.TrimSpace(input), "\n") - trees := make([][]byte, 0, len(lines)) - for _, line := range lines { - trees = append(trees, []byte(line)) - } - height := len(trees) - width := len(trees[0]) - - count := 0 - for y := 0; y < height; y++ { - for x := 0; x < width; x++ { - if isVisibleFromOutside(trees, x, y) { - count++ - } - } - } - fmt.Printf("%d visible trees\n", count) - - scenicScoreMap := make([][]int, height) - highestScenicScore := 0 - for y := 0; y < height; y++ { - scenicScoreMap[y] = make([]int, width) - for x := 0; x < width; x++ { - scenicScore := calculateScenicScore(trees, x, y) - scenicScoreMap[y][x] = scenicScore - if scenicScore > highestScenicScore { - highestScenicScore = scenicScore - } - } - } - fmt.Printf("highest scenic score %d\n", highestScenicScore) - printScenicScoreMap(scenicScoreMap) - - return nil -} diff --git a/days/8/input.txt b/days/8/input.txt deleted file mode 100644 index ffdd5b1..0000000 --- a/days/8/input.txt +++ /dev/null @@ -1,99 +0,0 @@ -011201001000123232122300403211332202122424332111151523152310403222120311202224013311113203311122001 -102201211220103202323002411123324024134251423232343141424431144431022143443131141222323122010012220 -002022232232102013311311301321044421352134513235443522243113311323213013301030440423203311103101020 -002212021110130112400112141310424411421435324412235335534245212325313312413434430114302030310200000 -202000312203303110042324124431114212153432535412115323131323541522511253002131401212012131031321110 -120203002030304244102444143021314124552253521343321513511124144454343454102412220143321013220111212 -012133330030200444414333325255125142322121412245551424242135123513411533153323130432231002121211210 -012300220003100211444401144353345522135453435223464636451554321531323513234331131114224102232333310 -000201310302031301344341134512444312432566266533252332656654251123535525135213300040211242011230031 -121002133124022203240512452433331223524622643252532325346635555552514352434233454024134201432001111 -112213110140442401434531255323512525265655352543623565556265545555235551143135124203142220020302000 -033001202421424143555311243322416262636322654432542644633525453666655354514351121150231101002002310 -133303044321221102531154151541224245536464535622566355532543644552554644312231415325142303020031312 -112333344411024045335422225146442243536464622553556234523445362524655623435243115242532313102020021 -123023422310204444121415255225254435644446326664473564435422565325224635623542352154120001224144312 -102303024142131515433355242322223363453633455657436436574636544336652564626641215232314243234004001 -021344140434455245134415553542352643537665534644574553367446664254532523624521243554252411433032112 -100140101131444142414254644644434663647646555637737475474473636562243265243536422253531252202124322 -111043301134142345422324342454235374733474673456744577746755765343355535622342432251442244140231224 -232120141224122324244532255543256467566454337465647735433663734756446566663442525425254525142212311 -102310340244433433553362546534535757453376643763344566566557634664535744445254533545223521213213014 -330111232252114431226334564636467643777466445537346735563633337744734474466254662225321443542401243 -344311321253412213666443354643647347656735478884748547564466577774737677363226422622515344334010341 -222340105234132533423442424376674757757675647476557547564445666676437755355626455436313331225343402 -334241221121414455435265324646757456774784864846746867457546648735456677555624445353555434433340341 -333430021343121666326363537633737767788775478777445558858444854755434544735362564626265444342330020 -332224425333452333556456745375454657668644877658744844547774765844454475434765533256545152435214410 -411322431421116436336347456774356844455867864644844878664785864444475567664473365652253123453220003 -130345455115155526426437663665665668576686587847778476557678655576775553535745643522532344433523042 -241333521455132466523664543556384776587787745658797755565556576546847447434775733626365325451531301 -202135433134452323646546565545646885747548679876767658578565476458486465755545465664435422532454541 -344025243154435524235475655536845545775797795959686975588855546544875685664377465455353661444452422 -120511445324333353265334766654858656857755669695597899959957757545465687447345336332322634434414522 -041425252513666643357433333888555778459755889566967799659865567757457567576463765323236366123221323 -142343534134652443554434768544658774587669979986775985989879787975445856456554364645323653454511323 -443155144123223566654765746758688875856899955996667659755976778586644774777456744653322566354532232 -013242522162435447764573774877757879868788876799896979576555597985885468586473474464455426633333452 -101431333345553353553337548577478656967866886877887889699999856979976485874455544477534422463331314 -422325541533664573334736464857446675995799977868697688998787757585668584775766563477536636621514142 -313315332565562573637376866486547776557979868979996867779966955885566785455767644565336236452541411 -231122455364326235655644685888786685587796897688777698977986787596655865857448333576665523356143332 -314415154446535337443754887576795586569678967879977696896667866768856785586774365336636426455324541 -251324556334435537567468544665859588888869687767876697967887867856679658788866355353346553442543353 -134353225423362456734666455757877769577678987866887877799886886885859796767664444665534363236114533 -251241346545626367667578575687955957988796678987999979977897978877579787844755554533763646262143315 -353543555544353753474346565789555799696999667888997899777669899867697878476845756644734243432245123 -221521465632632737777766744748678869769669668898887888987898666789869785645678734643552655525624335 -351552456455622567337644647486678857766866879798779999878779869885869788874885873744772665326352324 -153242153665224557353455465857685566797887699998988788877767696668668675666664465757646436665554315 -321113152666424547657348876876678597898779877779998999978978777885976658558676664444674243656333212 -421511245364456777655754476646885699898678788797778788778778999795687589454774563737333365434325525 -213532265252653474345766566877669898969767779777879797899977669868595997784466766655547455234435452 -125232235356525353764645486577668857868788699799787978898988669878688867586564457353673236664223343 -441242562562223643773466848558599657669669968987979987787969676777796877655876456745562442232541525 -135122156635652746574578664849659556998698797778797889988788869797687977855447474475546334662522444 -144315413442434666777478887855885568968799966889978797797867786966685589646488554737453225335213325 -511213234443636433646678657654587788667696879878989799867699988765895758788675765445656425425334544 -052145146243336363474565857687976889776768867898889967686967668565998666768575534675445244546424155 -235513424332444756467574556745997958679678999799789777998968876679956958746554677637762355253554335 -331155256654246447545776676487485655676699678967897779688898989999768655488874564764434223445132152 -152152253254255234473347878744485766678897879689897888667968795675655864748584644653323363464154251 -245154344235223346354765457746867586969968687876867899766986679689585778787473555663424264553541344 -235253541263666477544377746867785766579566868896689699876766695956667455774677646576554255521144355 -033522343456423455634354575764856898657669957896677776766596688857787474488436433455326554242331222 -321532413246333226435563556578864759978657759897896799958558598588975755858856537673332523244522141 -101422552442534324467345475684574877989759655788785857697957976679848768474665346435664653421242444 -103425135453353666736674677847548667967885667765576995797857589796866646565443377775564436443333543 -041131245522253556554636537878457787468577768876778599999689667978487755747676763666266652435545351 -424232344536333364556466767555646468677996965895798968676966868665587584664535544755645232211324114 -334034423343366322247357747635787857555667756956768657779596877655676555367754633345545442422145333 -424344345121532564223643563774744574746844686888885779565686455664565643634566756543362551431252401 -232123114442152332546734767375678475664877645798695799654765488755876545334345452455463633534433233 -414423121145222454332477456654436757485685646546884446667744645744675377357654436554353221451345404 -234130223314353235262655676637577858558554556467788664555466588778677546456334642623666524333250443 -414001252524152463224524734765775677644765886656877578666575855788653533364773455446565352432424320 -024323134311552535243564667476365737764685474446876486685546667685363735646643655435355533243440034 -331141044111451522226436327536773637654887585478885586588745847444466365767232265352211455413531431 -241321311312323233252665352455436545735388846445565487667644555744667753556266645332452431541341044 -234030032312154414563442653244476576544654676884777445766434443476675746365245632242515342521301442 -202112004552434344564624422526757574735736566643654737673776743354737744242533546523434111443034202 -323422334452422412134566522262537334374446646774476534347655656336555632626663364214333341322443300 -031243421344143515452456444553266345437737337675574563437533573575456463665443432215213541123241240 -002114441013421154331235436253442576764555535635775735635377573353666526333623554524421352131443020 -111342301013125124521245222663363363467436357434736773473777464564655622533254352444544553311114233 -222323000331131531351433363334345533653474663466435557365553376535246564324662454422135233103003200 -002103300342403311123432563445263435443255635353333564444573456633466424623313351545133022013122320 -300304042333200223123432352234525626625234236453763536563235242224645265643515312312520000242200000 -210121244033001141551213125554433445222532265463624234562324443435344362451243522525243002401410013 -303323342040431313415255233251226626334264553655346266323665655652522363324341123235410333230402230 -300112203021311400115231251543524354554262365526643622264625434236554412121342322522123434120120203 -011001023222004142422445443143212526654365444643442536365453622222634154551441553400220414300301332 -230032020342121242113341435444543253355352433246243543645634456552525315313143243431133302112320020 -232132202131312144424224413332214322543242664652323324456222615212244414145113442320023403200012111 -112222030320432400004224215552515412325221525356363643351335211141344255554442403013303120331312202 -110321230332323212301432002424211134155124241552254334221154111545254253122214132321141212032221001 -021020121321302320401011302153145251455114411155452245422422135453412153112033343412340101230302010 -122203012232330222213342133012334131225335225325343355122151154444535354414423434423220001330003020 -221120213213221333210131242440001425551432522221141211124544343151315104244333311124033221102312011 -202201033331203122413021242022211002455531321354252412214332215513311231404032244320020330332301120 diff --git a/days/8/sample.txt b/days/8/sample.txt deleted file mode 100644 index 16d6fbd..0000000 --- a/days/8/sample.txt +++ /dev/null @@ -1,5 +0,0 @@ -30373 -25512 -65332 -33549 -35390 diff --git a/days/9/day9.go b/days/9/day9.go deleted file mode 100644 index 68a545d..0000000 --- a/days/9/day9.go +++ /dev/null @@ -1,243 +0,0 @@ -package _9 - -import ( - _ "embed" - "fmt" - "math" - "strconv" - "strings" - - "github.com/ankon/adventofcode/2022/days" - "github.com/spf13/cobra" - "golang.org/x/exp/slices" -) - -//go:embed sample.txt -var sampleInput string - -//go:embed sample-2.txt -var sampleInput2 string - -//go:embed input.txt -var fullInput string - -var debug = false - -func ConfigureCommand(cmd *cobra.Command) { - cmd.Flags().BoolVar(&debug, "debug", false, "Enable debug output") -} - -func Run(useSampleInput bool) error { - input := days.PickInput(useSampleInput, sampleInput, fullInput) - - steps := strings.Split(strings.TrimSpace(input), "\n") - tail, err := runSteps(steps, 2) - if err != nil { - return nil - } - fmt.Printf("Unique points in tail trail (2 knots): %d\n", tail.uniquePoints()) - - input = days.PickInput(useSampleInput, sampleInput2, fullInput) - steps = strings.Split(strings.TrimSpace(input), "\n") - tail, err = runSteps(steps, 10) - if err != nil { - return nil - } - fmt.Printf("Unique points in tail trail (10 knots): %d\n", tail.uniquePoints()) - - return nil -} - -type point struct { - x, y int -} - -type trail struct { - symbol string - points []point - bottomLeft point - topRight point -} - -// Count the unique points in the trail -func (t *trail) uniquePoints() int { - var uniquePoints []point - for _, p := range t.points { - if !slices.Contains(uniquePoints, p) { - uniquePoints = append(uniquePoints, p) - } - } - - return len(uniquePoints) -} - -func (t *trail) current() point { - return t.points[len(t.points)-1] -} - -func (t *trail) add(p point) { - t.points = append(t.points, p) - if t.bottomLeft.x > p.x { - t.bottomLeft.x = p.x - } - if t.topRight.x < p.x { - t.topRight.x = p.x - } - if t.bottomLeft.y > p.y { - t.bottomLeft.y = p.y - } - if t.topRight.y < p.y { - t.topRight.y = p.y - } -} - -func (t *trail) follow(other *trail) { - // Check if the tail needs to move, if so, move it - head := other.current() - tail := t.current() - touches := head.x >= tail.x-1 && head.x <= tail.x+1 && head.y >= tail.y-1 && head.y <= tail.y+1 - if !touches { - dy := head.y - tail.y - if dy < 0 { - dy = -1 - } else if dy > 0 { - dy = +1 - } - dx := head.x - tail.x - if dx < 0 { - dx = -1 - } else if dx > 0 { - dx = +1 - } - newTail := point{tail.x + dx, tail.y + dy} - t.add(newTail) - } -} - -func (t *trail) show(otherPoints map[string]point) { - bottomLeft := t.bottomLeft - topRight := t.topRight - for _, p := range otherPoints { - if bottomLeft.x > p.x { - bottomLeft.x = p.x - } - if topRight.x < p.x { - topRight.x = p.x - } - if bottomLeft.y > p.y { - bottomLeft.y = p.y - } - if topRight.y < p.y { - topRight.y = p.y - } - } - - c := t.current() - for y := topRight.y; y >= bottomLeft.y; y-- { - line := fmt.Sprintf("%3d ", y) - for x := bottomLeft.x; x <= topRight.x; x++ { - p := point{x, y} - lowestK := math.MaxInt - symbol := "" - for s, otherPoint := range otherPoints { - if p == otherPoint { - k, err := strconv.Atoi(s) - if err == nil { - if k < lowestK { - lowestK = k - symbol = s - } - } else if s == "H" || lowestK == math.MaxInt { - symbol = s - } - } - } - if symbol != "" { - line += symbol - } else if p == c { - line += t.symbol - } else if slices.Contains(t.points, p) { - line += "#" - } else { - line += "." - } - - } - fmt.Println(line) - } -} - -func makeTrail(symbol string) *trail { - return &trail{ - symbol: symbol, - points: []point{{0, 0}}, - bottomLeft: point{0, 0}, - topRight: point{5, 5}, - } -} - -var directions = map[string]point{ - "R": {1, 0}, - "U": {0, 1}, - "L": {-1, 0}, - "D": {0, -1}, -} - -func runSteps(steps []string, knots int) (tail trail, err error) { - if knots < 2 { - return trail{}, fmt.Errorf("need at least 2 knots") - } - start := point{0, 0} - trails := make(map[int]*trail) - trails[0] = makeTrail("H") - if knots == 2 { - trails[1] = makeTrail("T") - } else { - i := 1 - for ; i < knots; i++ { - trails[i] = makeTrail(strconv.Itoa(i)) - } - } - for i, step := range steps { - d, c, found := strings.Cut(step, " ") - if !found { - return trail{}, fmt.Errorf("invalid step") - } - stepDelta, found := directions[d] - if !found { - return trail{}, fmt.Errorf("invalid direction %q", d) - } - count, err := strconv.Atoi(c) - if err != nil { - return trail{}, fmt.Errorf("invalid count %q", c) - } - - for i := 0; i < count; i++ { - // Move the head - head := trails[0].current() - newHead := point{ - head.x + stepDelta.x, - head.y + stepDelta.y, - } - trails[0].add(newHead) - for t := 1; t < knots; t++ { - trails[t].follow(trails[t-1]) - } - - if debug { - otherPoints := map[string]point{ - "s": start, - } - for t := 0; t < knots; t++ { - otherPoints[trails[t].symbol] = trails[t].current() - } - - fmt.Print("\033[H\033[2J") - trails[knots-1].show(otherPoints) - } - } - fmt.Printf("Processed %d/%d steps\n", i, len(steps)) - } - - return *trails[knots-1], nil -} diff --git a/days/9/input.txt b/days/9/input.txt deleted file mode 100644 index 448850e..0000000 --- a/days/9/input.txt +++ /dev/null @@ -1,2000 +0,0 @@ -D 2 -R 1 -U 1 -L 1 -D 2 -L 2 -R 1 -U 1 -D 2 -U 1 -R 1 -U 1 -D 2 -R 2 -L 2 -U 2 -D 1 -L 2 -R 2 -D 2 -U 2 -R 2 -U 1 -D 1 -L 2 -D 2 -L 2 -U 1 -R 2 -L 2 -D 2 -L 1 -D 2 -L 1 -R 2 -L 2 -U 1 -D 2 -L 1 -U 2 -R 1 -D 2 -L 2 -D 1 -L 2 -U 1 -L 1 -R 2 -U 2 -L 2 -D 1 -L 1 -D 1 -L 2 -R 1 -D 2 -U 2 -D 2 -R 1 -L 2 -R 2 -U 1 -R 1 -L 2 -U 2 -D 1 -U 2 -L 1 -R 2 -D 2 -L 2 -U 1 -L 1 -D 2 -R 2 -U 1 -R 2 -U 2 -D 2 -L 1 -U 1 -D 1 -R 1 -U 1 -D 2 -L 1 -D 2 -U 2 -D 1 -U 2 -L 2 -D 2 -R 2 -D 1 -R 2 -L 2 -U 1 -R 1 -L 1 -U 2 -D 2 -U 2 -L 2 -U 2 -R 2 -L 1 -U 1 -D 1 -L 2 -D 2 -R 2 -U 3 -R 3 -U 2 -L 1 -U 1 -L 1 -U 2 -R 2 -U 2 -D 1 -R 3 -D 1 -L 3 -R 2 -D 3 -U 1 -D 2 -L 2 -D 2 -L 1 -R 3 -D 1 -R 1 -L 3 -R 1 -U 2 -D 2 -L 3 -R 1 -U 2 -L 2 -R 3 -D 1 -U 2 -D 2 -L 3 -D 1 -R 3 -U 3 -R 2 -U 3 -D 1 -U 2 -R 2 -U 3 -R 1 -U 2 -L 3 -D 3 -U 1 -D 2 -U 2 -L 2 -R 1 -L 3 -R 1 -L 3 -U 2 -R 1 -U 1 -L 1 -R 2 -U 2 -D 1 -R 3 -D 3 -L 2 -D 2 -R 2 -L 3 -R 1 -L 1 -R 3 -L 3 -D 2 -U 1 -L 2 -U 3 -R 1 -L 1 -R 1 -L 1 -D 1 -R 2 -D 2 -U 1 -L 1 -D 3 -R 2 -D 1 -L 3 -R 3 -U 3 -D 2 -U 1 -D 2 -R 1 -U 1 -R 2 -D 2 -U 1 -D 3 -R 2 -U 3 -D 3 -R 1 -D 1 -U 2 -D 1 -U 2 -D 3 -U 3 -D 2 -R 4 -D 2 -R 1 -L 4 -U 2 -D 1 -U 2 -R 2 -U 1 -R 1 -U 4 -L 4 -U 3 -L 2 -U 3 -D 3 -R 2 -L 2 -U 3 -D 1 -L 3 -U 1 -L 1 -U 2 -L 4 -R 3 -U 3 -D 1 -L 3 -R 4 -D 4 -L 3 -R 4 -D 1 -R 4 -D 1 -L 3 -D 1 -L 1 -U 2 -D 1 -U 4 -R 1 -D 2 -U 2 -D 4 -U 3 -D 2 -L 4 -R 3 -U 3 -R 2 -D 3 -U 4 -R 4 -L 3 -U 2 -D 2 -U 2 -L 1 -R 3 -D 4 -U 1 -D 2 -U 1 -R 2 -L 2 -R 3 -U 4 -D 1 -L 1 -R 1 -D 4 -L 4 -D 4 -L 2 -R 3 -L 1 -U 2 -L 1 -D 3 -U 2 -R 2 -D 1 -R 1 -U 1 -L 2 -D 2 -U 3 -L 3 -U 1 -L 1 -D 1 -L 3 -R 4 -L 2 -R 1 -U 2 -D 4 -U 2 -L 4 -U 4 -R 1 -D 3 -U 2 -L 2 -D 4 -L 2 -U 1 -D 5 -L 5 -R 1 -D 1 -L 4 -D 5 -R 4 -U 2 -R 2 -L 2 -D 3 -U 4 -L 1 -U 1 -R 2 -L 4 -R 3 -U 1 -D 5 -U 4 -D 2 -R 3 -L 1 -D 4 -L 5 -D 1 -L 2 -U 1 -R 2 -L 2 -R 1 -L 2 -U 4 -D 1 -U 5 -L 2 -R 1 -D 5 -L 2 -D 5 -U 5 -R 3 -L 4 -D 2 -L 2 -D 2 -U 5 -R 3 -U 1 -D 3 -R 4 -U 3 -R 2 -U 3 -D 5 -U 4 -L 3 -R 3 -D 3 -R 1 -L 1 -D 4 -R 3 -D 2 -L 2 -R 4 -L 3 -R 2 -D 4 -L 3 -U 1 -D 2 -L 3 -U 4 -D 5 -U 2 -L 2 -R 1 -D 1 -L 3 -U 2 -R 4 -D 4 -L 4 -U 2 -D 1 -R 5 -L 3 -U 3 -L 5 -R 2 -D 1 -L 2 -D 2 -L 2 -R 4 -L 3 -D 3 -R 5 -L 5 -D 3 -R 5 -L 2 -R 1 -D 4 -L 2 -D 1 -U 2 -D 4 -U 5 -L 4 -D 2 -U 2 -D 4 -U 6 -L 3 -U 1 -D 2 -R 1 -U 5 -D 2 -L 4 -R 6 -U 2 -L 2 -D 1 -R 5 -U 2 -D 5 -R 5 -U 4 -D 6 -U 1 -D 2 -U 5 -D 5 -L 6 -U 5 -D 6 -L 4 -U 6 -R 5 -L 6 -D 5 -L 5 -D 6 -U 5 -L 6 -U 5 -L 3 -R 2 -D 1 -R 1 -L 6 -U 5 -D 1 -R 2 -D 2 -L 2 -D 6 -U 6 -L 1 -R 6 -L 3 -D 6 -R 3 -D 2 -U 5 -D 4 -L 2 -R 3 -D 5 -U 1 -D 3 -R 6 -U 4 -L 4 -U 4 -D 1 -R 4 -U 2 -R 6 -L 1 -D 3 -R 3 -U 1 -L 6 -R 4 -D 2 -U 2 -D 6 -L 4 -R 6 -U 3 -R 3 -D 3 -L 1 -R 5 -U 4 -R 6 -L 2 -R 1 -U 1 -L 6 -D 6 -L 3 -R 2 -D 6 -R 6 -L 3 -U 3 -D 1 -L 3 -D 1 -R 4 -D 3 -U 3 -D 2 -U 6 -D 4 -L 4 -R 5 -D 1 -L 7 -R 3 -L 5 -R 3 -U 6 -L 5 -U 3 -D 1 -L 5 -R 4 -L 1 -U 6 -L 1 -R 4 -D 3 -R 7 -D 7 -R 4 -L 4 -D 4 -L 2 -R 1 -U 7 -L 1 -D 7 -L 1 -D 1 -R 5 -D 5 -U 2 -L 6 -R 2 -U 5 -L 7 -D 7 -L 7 -U 1 -L 6 -D 2 -L 6 -U 2 -R 4 -U 7 -D 2 -L 6 -U 7 -R 5 -U 7 -L 7 -D 2 -R 4 -U 6 -R 1 -D 3 -R 2 -L 5 -R 5 -U 3 -L 5 -U 4 -D 4 -L 5 -R 1 -L 4 -D 5 -U 1 -L 4 -D 7 -R 6 -D 7 -U 7 -D 4 -R 1 -D 2 -L 5 -R 4 -D 3 -U 2 -D 4 -R 3 -L 4 -R 4 -U 3 -D 7 -R 2 -L 1 -D 5 -R 3 -D 2 -L 7 -R 3 -D 5 -R 1 -D 2 -R 6 -L 5 -R 7 -L 5 -U 2 -R 3 -D 6 -L 1 -D 4 -R 2 -U 1 -D 1 -R 6 -D 5 -L 3 -R 7 -L 3 -U 5 -R 5 -U 3 -D 8 -L 2 -U 6 -L 8 -U 4 -D 5 -R 7 -U 7 -L 4 -R 3 -L 3 -D 1 -L 6 -R 5 -L 6 -R 6 -L 8 -D 3 -U 2 -L 7 -R 2 -U 8 -D 3 -L 4 -R 3 -U 8 -R 3 -U 6 -D 8 -R 2 -L 8 -U 2 -R 5 -D 1 -U 1 -D 8 -R 4 -L 7 -D 2 -U 3 -D 1 -R 2 -U 1 -L 5 -U 4 -R 5 -D 6 -L 3 -U 1 -D 6 -U 6 -D 6 -U 2 -L 6 -U 6 -D 5 -L 1 -D 7 -U 2 -D 4 -L 5 -R 4 -D 2 -L 6 -U 2 -R 1 -U 4 -L 3 -D 3 -R 6 -D 4 -R 3 -L 2 -U 8 -R 5 -L 2 -U 3 -R 7 -U 7 -R 4 -U 5 -D 1 -L 8 -R 8 -U 3 -L 1 -U 7 -L 7 -D 2 -L 8 -D 7 -R 7 -L 3 -R 4 -L 3 -R 4 -U 6 -L 5 -R 4 -U 7 -L 3 -D 3 -R 2 -L 6 -U 3 -L 1 -R 8 -L 6 -D 7 -L 8 -R 7 -L 6 -D 2 -U 2 -R 3 -L 9 -R 7 -D 1 -R 9 -L 2 -D 5 -U 7 -D 5 -U 4 -L 4 -D 5 -L 6 -R 3 -U 2 -R 6 -D 3 -U 2 -R 1 -D 5 -U 6 -L 8 -D 8 -U 9 -L 2 -U 5 -L 2 -U 3 -L 4 -U 6 -L 3 -D 2 -R 5 -L 3 -R 8 -D 8 -U 8 -R 4 -U 2 -D 3 -L 9 -U 2 -L 4 -U 5 -R 5 -L 7 -U 9 -L 7 -U 5 -L 6 -U 6 -R 5 -L 9 -U 9 -R 3 -D 8 -U 8 -R 9 -D 4 -U 9 -D 9 -L 3 -R 2 -D 3 -U 1 -R 7 -D 5 -U 9 -D 7 -U 3 -D 8 -L 9 -U 1 -R 6 -L 8 -R 2 -L 7 -D 3 -U 4 -D 9 -L 1 -R 4 -D 9 -U 1 -D 1 -L 8 -U 2 -D 8 -U 1 -L 1 -U 2 -D 7 -L 1 -D 2 -L 6 -U 2 -D 8 -R 7 -L 4 -U 5 -R 2 -U 8 -D 6 -R 3 -D 8 -R 4 -L 5 -U 4 -L 1 -U 6 -L 10 -D 7 -R 5 -D 9 -U 6 -D 5 -L 9 -U 2 -R 3 -U 7 -R 7 -D 1 -R 4 -U 10 -D 4 -R 7 -L 7 -D 3 -R 5 -U 5 -D 6 -U 2 -D 2 -U 6 -D 5 -L 6 -U 10 -D 7 -R 6 -L 9 -R 7 -L 7 -U 6 -D 6 -R 8 -D 8 -R 4 -D 4 -L 1 -R 3 -U 5 -R 2 -L 9 -R 8 -L 3 -U 3 -R 6 -U 2 -L 6 -U 4 -D 5 -R 6 -U 5 -R 8 -U 10 -L 5 -U 2 -R 1 -D 9 -U 8 -D 2 -U 9 -L 7 -R 2 -D 10 -L 7 -D 3 -R 4 -L 2 -U 2 -R 7 -U 6 -D 9 -U 8 -L 7 -D 4 -U 4 -R 6 -U 3 -D 9 -L 1 -U 9 -R 9 -D 4 -L 9 -R 6 -L 6 -U 9 -L 10 -R 1 -L 5 -R 1 -L 2 -D 8 -U 2 -L 1 -R 4 -U 9 -L 3 -D 9 -L 6 -R 8 -U 6 -R 8 -L 5 -D 2 -R 5 -U 8 -R 2 -L 9 -R 3 -U 3 -R 8 -U 5 -D 5 -U 8 -D 10 -R 4 -L 5 -U 2 -L 4 -D 2 -L 1 -D 3 -U 8 -D 3 -U 4 -L 6 -D 6 -U 9 -L 5 -D 5 -U 10 -R 9 -D 2 -U 11 -D 4 -L 8 -D 8 -L 4 -U 6 -D 3 -R 9 -U 11 -L 7 -U 7 -D 9 -U 10 -D 9 -U 2 -R 2 -U 7 -R 2 -U 10 -R 7 -L 7 -U 6 -D 10 -L 5 -U 4 -D 4 -L 3 -D 3 -L 2 -R 5 -D 5 -U 10 -R 3 -U 8 -L 10 -U 5 -R 3 -L 9 -R 5 -D 1 -L 8 -R 8 -D 10 -L 6 -D 5 -L 6 -R 7 -D 10 -U 3 -D 9 -L 8 -D 5 -U 10 -L 5 -U 4 -D 7 -U 11 -L 6 -U 6 -L 9 -R 6 -U 8 -R 8 -L 6 -U 8 -L 8 -U 9 -D 4 -L 10 -D 6 -R 5 -D 8 -L 7 -D 6 -R 4 -D 11 -U 5 -D 4 -R 7 -U 11 -L 5 -U 7 -D 7 -L 11 -R 9 -U 1 -D 11 -R 8 -L 4 -R 2 -D 6 -L 4 -R 8 -D 9 -R 11 -U 2 -L 9 -U 6 -R 10 -L 11 -R 9 -D 10 -U 11 -L 6 -U 3 -L 2 -R 11 -L 2 -D 2 -L 5 -D 6 -U 11 -D 10 -U 8 -L 3 -R 9 -D 5 -R 9 -D 6 -R 2 -U 2 -D 11 -R 6 -U 9 -R 12 -U 6 -L 1 -D 2 -L 5 -D 9 -L 5 -D 4 -U 10 -L 12 -U 6 -R 6 -U 4 -L 4 -U 1 -L 4 -R 12 -L 11 -R 3 -U 10 -L 4 -R 11 -D 9 -L 9 -U 11 -D 1 -L 1 -R 3 -D 7 -U 6 -R 4 -D 3 -L 8 -U 5 -R 6 -L 9 -U 4 -L 6 -D 6 -U 6 -L 5 -R 7 -D 10 -R 5 -U 8 -L 5 -R 6 -U 10 -R 2 -U 2 -R 10 -U 12 -D 12 -L 7 -U 3 -R 1 -L 6 -D 6 -L 5 -D 8 -U 8 -D 11 -L 2 -D 10 -L 6 -R 10 -L 9 -D 5 -R 1 -D 7 -R 6 -U 10 -D 8 -R 9 -D 11 -R 8 -U 7 -R 10 -L 1 -U 3 -R 11 -D 11 -L 8 -D 13 -U 6 -D 12 -U 2 -L 2 -U 11 -D 1 -R 3 -U 8 -R 4 -L 3 -U 7 -D 4 -L 3 -R 2 -L 3 -R 6 -D 13 -L 1 -R 8 -L 5 -R 11 -D 7 -L 8 -D 12 -U 12 -D 3 -L 6 -U 1 -R 7 -U 2 -D 9 -L 3 -U 11 -R 2 -U 6 -D 11 -L 10 -D 4 -U 13 -D 1 -R 11 -L 3 -U 2 -D 7 -R 8 -D 10 -R 12 -D 4 -R 1 -U 5 -R 5 -U 2 -R 12 -D 3 -L 8 -D 11 -U 3 -R 1 -U 2 -R 3 -D 5 -U 8 -D 4 -R 6 -L 2 -R 4 -U 6 -D 12 -L 7 -U 2 -L 8 -U 8 -R 13 -U 10 -L 11 -R 1 -D 4 -R 1 -U 5 -L 9 -D 9 -U 11 -D 13 -U 9 -R 2 -D 9 -U 6 -R 1 -D 12 -R 3 -U 1 -R 13 -U 11 -L 6 -R 3 -D 11 -U 13 -R 2 -U 8 -L 11 -R 12 -D 7 -L 11 -U 10 -D 2 -L 9 -R 1 -L 9 -R 10 -D 5 -U 7 -R 6 -D 11 -U 11 -L 7 -R 6 -L 12 -D 12 -L 5 -R 3 -L 12 -R 4 -L 7 -D 4 -U 11 -R 2 -L 9 -R 11 -D 14 -L 7 -R 10 -U 1 -D 2 -L 7 -D 2 -U 12 -R 2 -D 6 -R 12 -L 7 -D 4 -U 13 -L 11 -D 13 -R 11 -D 5 -U 14 -R 1 -L 8 -U 10 -R 3 -D 3 -L 13 -R 6 -U 5 -D 4 -L 12 -D 2 -R 9 -D 1 -R 7 -D 10 -U 14 -L 12 -R 11 -U 6 -D 11 -L 8 -D 2 -U 4 -L 1 -R 14 -D 8 -U 11 -L 13 -U 1 -D 2 -R 14 -D 10 -R 4 -L 1 -R 10 -U 9 -D 8 -L 10 -R 10 -U 6 -D 14 -L 10 -U 13 -R 8 -L 3 -D 6 -L 13 -D 11 -U 14 -R 13 -U 12 -L 2 -D 6 -U 13 -L 13 -U 12 -D 1 -U 10 -L 5 -U 3 -R 4 -D 10 -L 14 -U 8 -R 7 -U 6 -R 13 -D 14 -L 5 -U 6 -L 1 -D 7 -R 2 -D 14 -U 13 -R 3 -U 5 -R 13 -L 2 -D 12 -U 1 -R 11 -L 7 -U 2 -D 11 -L 2 -R 7 -D 7 -L 1 -U 10 -L 12 -R 6 -L 7 -R 4 -D 3 -R 3 -U 15 -D 13 -U 6 -D 6 -U 3 -R 14 -U 10 -L 1 -R 8 -D 7 -R 13 -D 10 -R 9 -U 11 -D 11 -U 4 -D 11 -U 10 -D 3 -R 12 -U 5 -D 1 -L 4 -R 10 -D 11 -U 2 -D 9 -U 12 -D 9 -R 3 -D 6 -U 4 -L 14 -R 15 -U 4 -D 11 -R 13 -L 3 -U 12 -R 5 -U 11 -L 11 -D 6 -U 15 -R 5 -U 5 -R 1 -D 8 -U 4 -L 12 -D 2 -U 9 -L 15 -D 6 -R 12 -L 10 -D 14 -R 14 -D 8 -L 2 -D 11 -U 13 -L 1 -R 8 -D 8 -L 5 -D 14 -R 10 -U 13 -R 10 -L 4 -R 5 -L 6 -U 7 -R 7 -L 5 -D 3 -L 15 -U 10 -D 6 -L 1 -R 15 -D 11 -U 13 -R 12 -U 4 -D 8 -L 4 -D 11 -R 12 -L 5 -D 2 -U 8 -D 8 -L 10 -U 16 -L 15 -D 9 -U 10 -R 16 -L 7 -R 7 -U 9 -D 12 -L 16 -U 12 -R 13 -U 5 -R 5 -U 8 -D 8 -U 15 -L 4 -R 2 -L 2 -U 10 -D 2 -U 6 -L 15 -R 11 -D 2 -L 5 -R 16 -L 13 -R 14 -U 5 -R 2 -L 11 -U 9 -D 4 -L 14 -U 6 -D 6 -U 7 -D 2 -U 5 -D 6 -U 10 -D 5 -L 11 -R 13 -L 9 -U 5 -R 7 -D 13 -U 12 -L 6 -U 14 -R 15 -L 3 -U 4 -D 4 -U 8 -R 1 -U 12 -L 7 -U 2 -L 11 -R 10 -D 6 -R 9 -L 6 -R 2 -L 16 -U 8 -D 16 -R 8 -U 7 -D 7 -U 12 -D 13 -L 14 -R 3 -U 7 -L 14 -R 14 -U 4 -D 15 -R 13 -D 2 -R 9 -D 14 -U 15 -D 8 -L 8 -R 10 -U 4 -D 5 -L 16 -D 17 -R 14 -U 10 -D 15 -L 15 -R 13 -L 17 -U 12 -R 1 -D 8 -U 2 -R 11 -U 8 -D 9 -R 6 -U 10 -D 3 -L 7 -R 4 -L 15 -U 14 -L 9 -R 15 -U 9 -D 5 -U 4 -D 10 -R 13 -U 9 -D 5 -R 12 -D 6 -U 7 -D 8 -L 7 -U 13 -D 5 -R 4 -L 10 -D 16 -L 11 -R 16 -L 16 -U 15 -D 1 -R 3 -L 13 -D 7 -U 1 -R 15 -U 15 -D 2 -U 3 -L 7 -U 4 -D 14 -L 10 -D 8 -U 8 -D 6 -R 16 -U 6 -D 7 -L 13 -U 3 -L 9 -R 10 -D 5 -R 2 -D 16 -U 14 -R 11 -D 10 -R 13 -U 12 -L 4 -U 7 -L 2 -R 5 -D 13 -U 3 -R 3 -U 16 -L 5 -R 13 -L 16 -D 7 -L 4 -R 14 -U 8 -L 9 -U 2 -L 10 -D 9 -R 17 -U 14 -R 2 -D 7 -U 14 -R 3 -U 3 -L 14 -D 16 -U 6 -L 5 -U 2 -R 7 -L 4 -U 3 -D 12 -L 7 -D 15 -U 6 -L 1 -D 5 -U 11 -L 9 -D 15 -L 12 -R 18 -L 4 -D 9 -U 17 -R 1 -D 5 -L 13 -U 16 -R 17 -U 10 -D 5 -L 16 -D 2 -R 10 -L 1 -U 14 -L 16 -U 3 -D 2 -R 5 -U 3 -R 17 -D 17 -L 15 -U 11 -L 16 -R 4 -L 3 -R 7 -L 5 -R 8 -U 15 -R 9 -U 9 -R 18 -L 17 -R 9 -U 18 -L 11 -U 14 -R 7 -L 16 -R 15 -L 1 -U 9 -L 10 -U 9 -L 14 -U 5 -D 1 -R 16 -D 6 -R 1 -D 14 -R 11 -U 10 -D 17 -L 12 -D 5 -U 4 -L 12 -U 1 -L 7 -R 13 -D 2 -U 14 -D 3 -U 6 -R 1 -U 2 -R 11 -U 9 -D 14 -R 9 -U 14 -R 9 -D 14 -R 2 -D 9 -U 8 -D 10 -U 3 -R 8 -D 11 -R 5 -U 4 -D 1 -U 16 -L 17 -U 1 -R 14 -U 10 -R 5 -U 12 -D 4 -R 10 -D 10 -L 5 -R 2 -L 18 -D 3 -L 17 -D 10 -U 4 -L 15 -U 4 -L 9 -U 14 -R 9 -U 16 -L 1 -R 7 -U 10 -D 1 -U 13 -D 15 -R 6 -U 2 -L 17 -U 11 -L 14 -U 12 -R 11 -U 4 -D 11 -R 7 -D 13 -U 16 -L 5 -U 7 -R 4 -L 17 -D 2 -U 18 -R 8 -U 16 -L 15 -R 8 -L 19 -U 17 -D 2 -U 8 -D 9 -U 3 -L 12 -U 16 -L 3 -R 14 -D 16 -U 11 -D 2 -L 16 -U 4 -L 18 -R 15 -U 9 -L 18 -U 11 -R 18 -L 13 -D 8 -U 12 -D 14 -L 12 -U 2 -D 13 -L 12 -U 16 -R 17 -L 14 -U 10 -R 15 -U 19 -L 17 -R 8 -L 17 -R 8 -U 4 -R 8 -U 11 -L 17 -R 8 -D 13 -U 6 -D 7 -R 9 -L 2 -R 4 -D 16 -L 2 -D 10 -U 4 -L 10 -D 14 -U 5 -D 7 -U 4 -D 16 -U 14 -L 4 -U 14 -L 3 -D 16 -L 14 -U 11 -D 3 -L 10 -U 8 -D 6 -L 9 -D 17 -R 16 diff --git a/days/9/sample-2.txt b/days/9/sample-2.txt deleted file mode 100644 index 60bd43b..0000000 --- a/days/9/sample-2.txt +++ /dev/null @@ -1,8 +0,0 @@ -R 5 -U 8 -L 8 -D 3 -R 17 -D 10 -L 25 -U 20 diff --git a/days/9/sample.txt b/days/9/sample.txt deleted file mode 100644 index 9874df2..0000000 --- a/days/9/sample.txt +++ /dev/null @@ -1,8 +0,0 @@ -R 4 -U 4 -L 3 -D 1 -R 4 -D 1 -L 5 -R 2 diff --git a/days/util.go b/days/util.go deleted file mode 100644 index 69b18b3..0000000 --- a/days/util.go +++ /dev/null @@ -1,9 +0,0 @@ -package days - -func PickInput(useSampleInput bool, sampleInput string, fullInput string) string { - if useSampleInput { - return sampleInput - } else { - return fullInput - } -} diff --git a/go.mod b/go.mod deleted file mode 100644 index ba8fe9d..0000000 --- a/go.mod +++ /dev/null @@ -1,11 +0,0 @@ -module github.com/ankon/adventofcode/2022 - -go 1.19 - -require github.com/spf13/cobra v1.6.1 - -require ( - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 370408c..0000000 --- a/go.sum +++ /dev/null @@ -1,13 +0,0 @@ -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 h1:yZNXmy+j/JpX19vZkVktWqAo7Gny4PBWYYK3zskGpx4= -golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go deleted file mode 100644 index ce28597..0000000 --- a/main.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import "github.com/ankon/adventofcode/2022/cmd" - -func main() { - cmd.Execute() -} diff --git a/utils/modulo.go b/utils/modulo.go deleted file mode 100644 index af8f2e7..0000000 --- a/utils/modulo.go +++ /dev/null @@ -1,34 +0,0 @@ -package utils - -// MultiplyMod multiplies two numbers modulo m -// -// Taken from https://en.wikipedia.org/wiki/Modular_arithmetic#Example_implementations -func MultiplyMod(a, b, m uint64) uint64 { - if ((a | b) & (0xFFFFFFFF << 32)) == 0 { - return a * b % m - } - - d := uint64(0) - mp2 := m >> 1 - if a >= m { - a %= m - } - if b >= m { - b %= m - } - for i := 0; i < 64; i++ { - if d > mp2 { - d = (d << 1) - m - } else { - d <<= 1 - } - if a&0x8000000000000000 != 0 { - d += b - } - if d >= m { - d -= m - } - a <<= 1 - } - return d -} diff --git a/utils/prime.go b/utils/prime.go deleted file mode 100644 index 971208a..0000000 --- a/utils/prime.go +++ /dev/null @@ -1,37 +0,0 @@ -package utils - -import ( - "math" - "sort" -) - -var knownPrimes = []int{2,3,5,7,11,13,17,19,23} - -func nextPrimeAfter(n int) int { - i := sort.SearchInts(knownPrimes, n + 1) - if i < len(knownPrimes) { - return knownPrimes[i] - } - for x := knownPrimes[i - 1] + 2; ; x++ { - if IsPrime(x) { - if len(knownPrimes) < 1000 { - knownPrimes = append(knownPrimes, x) - } - return x - } - } -} - -func IsPrime(p int) bool { - if p == 2 || p == 3 { - return true - } - - max := int(math.Ceil(math.Sqrt(float64(p)))) - for d := 2; d <= max; d = nextPrimeAfter(d) { - if p%d == 0 { - return false - } - } - return true -} diff --git a/utils/stack.go b/utils/stack.go deleted file mode 100644 index 3e9e730..0000000 --- a/utils/stack.go +++ /dev/null @@ -1,31 +0,0 @@ -package utils - -type Stack[T any] struct { - data []T -} - -func (s *Stack[T]) Len() int { - return len(s.data) -} - -func (s *Stack[T]) Top() T { - return s.data[len(s.data)-1] -} - -func (s *Stack[T]) Pop() T { - end := len(s.data)-1 - result := s.data[end] - s.data = s.data[:end] - return result -} - -func (s *Stack[T]) Push(x T) { - s.data = append(s.data, x) -} - -func (s *Stack[T]) Clone() Stack[T] { - result := Stack[T]{ - data: append([]T{}, s.data...), - } - return result -} From 75dcf2c4a870e81792fc28d57d5094090d1bbb46 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 2 Dec 2023 15:36:42 +0100 Subject: [PATCH 058/120] Implement the most basic first test --- .gitignore | 1 + .vscode/extensions.json | 1 + .vscode/launch.json | 13 ++++++--- .vscode/settings.json | 1 + Cargo.lock | 7 +++++ Cargo.toml | 12 ++++++++ README.md | 5 +++- src/main.rs | 65 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore index 0100b4b..6a5f09e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ # Binaries +/target diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 3d97f9e..761dd61 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,6 @@ { "recommendations": [ "rust-lang.rust-analyzer", + "ms-vscode.cpptools", ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 8a7ebe2..b138b62 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,8 +1,13 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", "configurations": [ + { + "type": "cppdbg", + "request": "launch", + "name": "run adventofcode", + "program": "${workspaceFolder}/target/debug/adventofcode", + "args": [], + "cwd": "${workspaceFolder}", + "sourceFileMap": {}, + } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 33de8df..6537445 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "editor.formatOnSave": true, "editor.formatOnSaveMode": "modificationsIfAvailable", + "rust-analyzer.check.command": "clippy", } diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..f26e54c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adventofcode" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b98fdda --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "adventofcode" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[[bin]] +name = "adventofcode" +path = "src/main.rs" diff --git a/README.md b/README.md index b37c775..3a9f196 100644 --- a/README.md +++ b/README.md @@ -4,5 +4,8 @@ My attempts at [saving the holidays](https://adventofcode.com/). ## 2023 Update -This year, let's see how Rust fares. +This year, let's see how Rust fares: Install the needed parts first! +```sh +dnf install rust rust-src cargo clippy +``` diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..da2d3e5 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,65 @@ +const TEST_STR: &str = "1abc2 +pqr3stu8vwx +a1b2c3d4e5f +treb7uchet"; + +#[derive(Debug)] +struct Line { + first: Option, + last: Option, +} + +impl Line { + fn new() -> Line { + Line { + first: None, + last: None, + } + } + + fn visit_digit(&mut self, digit: i32) { + if self.first.is_none() { + self.first = Some(digit); + } else { + self.last = Some(digit); + } + } + + fn value(&self) -> i32 { + let first = self.first.unwrap(); + if let Some(last) = self.last { + 10 * last + first + } else { + 10 * first + first + } + } +} + +impl std::str::FromStr for Line { + type Err = (); + + fn from_str(s: &str) -> Result { + let mut line = Line::new(); + for c in s.chars().rev() { + if let '0'..='9' = c { + let digit = c.to_digit(10).unwrap(); + line.visit_digit(digit as i32); + } + } + Ok(line) + } +} + +fn calculate_calibration_value(input: &str) -> i32 { + let mut result = 0; + for line in input.lines() { + let parsed_line = line.parse::().unwrap(); + println!("parsed_line = {:?}", parsed_line); + result += parsed_line.value(); + } + result +} + +fn main() { + println!("test value = {}", calculate_calibration_value(TEST_STR)); +} From 6b635d86efc886378a1ea6d4169bea1843b33021 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 2 Dec 2023 15:50:01 +0100 Subject: [PATCH 059/120] Read from the input file --- day1.input | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 + 2 files changed, 1004 insertions(+) create mode 100644 day1.input diff --git a/day1.input b/day1.input new file mode 100644 index 0000000..397f90f --- /dev/null +++ b/day1.input @@ -0,0 +1,1000 @@ +tmmnhlxzpj1eightldxhjnone97 +9fivekfpl855mjmfdqzvbn +two29eighteight1 +4md +sixbrqklb347 +6sevenninexpnbgbr11three15 +4zggkljkcqthree7 +7lxjkqhmxcxsevennhszsbxzdfsonehnsrcfour9 +jtpmfoureightvtjmlshbfour6nvjkqnddp3 +twofive2fourfive1dvnrrvjr +twoeightnq6ninepxv +39sixgphfvninexts71five +seven3two8 +six59jhtfvv1five6 +7871three915 +prrvrjlpgxpjdxfchqonepchqbhqxx9nbrvh +gneightwo5txxzpkctwojvrcgbd9 +329 +5mnmpsevenseven +ccshz8 +threeqthree5eight6blzzh +moneight3onepkjskr9 +ctdk8zkhzzkt +nbfrmvlnmbeightbxs55 +six5mrrvsxqhqj162sevenntsnztmsdbnine +78dlfqtsplmnbrtfive3tskrrjnqktrkrfdxps +rljhmtwotwo5sevenfourtwo +6drnzxz9fourfourfourxfxsxhlzqx +7two8dvhghtd +five277 +four7mfhfcpqjjvlxvbs +sixhdxxhrzrsjthree2zddffivevzkcppvpshh +hnsnbldnp5hdfzqnine +kbdfmgjtfxzszl6fourtwo72eight +4fourxrtvjh +dzbfkvzlg6ngnrsevenzfqmlldc7 +eighthg62txtxhkl9 +5dckmbonetwolgsixvvftfive +twordkznxxffour3jgxhl95 +eightsix4twofoursgdlfkjonefoureight +9qlh1ztk9 +fourrmbrseventwo4pmdmlkp +sevenfive6gbcfslxhkmqlvspvgjgpsrffive22 +34threejhd9one83 +577twomg +threethreezcl9tkhjgqhknrmscpppjnnlnrtrx1 +tjxtcnxbq1sevensixfhhnfour +4six3kcnkonegxpfj +knhpcljnjhfive5seveneightck7three +rvrr1 +jjqvphczpqdmszgbqnsevennine81 +54568 +97zvmkrslhzvvrjgknjsevenfive1four +8onenine4mpfdsixfzhtpz7 +rdgjphdxkmmrh6fiver9ninetwojgxpghhp +gdhk3twonine91zzzmmone4 +qsxvlxkfnpvdthqteight24nine4 +sixeightthreesixfivevf3qfpvzvnt +five4nkqfcdpqn3fourcqfjjkdnjxf +xkpmtmhxlxfourvdsjmpsltr1xk7 +threezqkb4 +h2ckfnlk +kzngqxt27fourtwo +lgzhoneeight7fivenineseven5 +2fivesmzgdnsqcm +4n442ptkfx +sbkdpn2nhdjqc +bh22eightdqvhpspx +hdmdg7kjr4 +three3jttm7fourfourckm7spkhqdtv +1twoone2911 +dvhmdbjlhfqllkrgnine1ttjvczdsrk5trngnvlnfnone +two3pbdvzqonefour3bzktxlgdeight +7eightjcjkqldhpqfrlt9nine +2jvdfdcsnnsonejbxqrmhdjthreesix +7pxbhzglcb283sixnine4 +38npgninefive2two6 +jqeightwo7dzfcxppxgtsixfl966qzlbpczz +sevennine3bvdzkrjff +25hninehtwothreeseven +xdrkprvdmd8fiveftwopkcbfhtxmtkjmklzpphjjtqjfvvh +2slfjzgflnhmc +2bqnbkd +twothreeeighteight8gnhccvzfour8 +3six2two3btddfjt1 +eightbcmnpnmq7hcqd1kkbjmtnlcjsixoneightvrh +v99zsseven92five +fourzngffive1five5threethree +onesix36 +sixtwo6qlfm6onetwogfive +pkzjfive4sqknbg4gqbqmdzczcqrds +9sdgnqdnxqpjgmfourfour8lbrskpnglp +sevennpxtlltn7eightzfhkltfsixsixtwo +xjhfour9 +7rmtwo +nine1seven8 +oneqcnrjbqnbzfbxz4eight68 +seven5four968five +lhzgtxxdr7seven +lgconeighthtrvbkp17one8jsxhbxhvqr +41three +seventstcfbjbmsixtwothreefourtwojsbrdlml2 +8one5nbpmdhcfjhtwohbjhmzttmr9 +cvcl644eightmzzsqstzjkn +mxgj1seventwolttplthree +33nine63twosixrgrrzsgj +seveneight1 +jqdp16six +893plhbfvfc2threetwo3 +6qhfhzsclsmvcpxfjxkl +two8nine +sevenfivetwo1pn +threeone4fkpdk81trqfivepgrvdbd +8rtwofhfthngbnphrsn8fr1mq +235 +pztmvdb9fiveeighthgqvnine6 +8jqv +9sevenhcdntl4eight +682onepdphj5 +fstfvxrxt86jkzmlvnzfivethreecbnsevenfive +eightfive4ninenine3ktndjdhb4 +7twoflphhdcs +9thvn912mdcpfn8 +pxfvghsvtxsevenfivesevenninecck7onenine +sixvd2xmnxrtvfhcng +fiveoneseven96eighttwo +eighttwo6fourgggthreefzpbxmq +9zlkfnbfb +nhmssnx2 +oneeighteightfive5mlzbnxlgthree7nzkhl +rqrxzkpmglsixvmvrcgtlptkz9grhvhstknq +three12five44onevglccksrpgxkc +3oneseven4mjtwofour +fmcmjgvbfonesix3ninemninefivethree +sixvlvxxtwo77 +fivefour4 +51six +37lrmmfmjjn8six +twozzfcz3nineslvv8one +1fourninesix6sixmjngkmsntrnvmtwonehrn +oneeight3four12hqnjxlfxtg1 +9dlqkqgbsvxqnrk +1cxfptmfnschgkdl +threefccrrscjcg194 +seven65kn34five9 +2lrnxvs1 +nine91bqvl2six8five +twoeight9xkmmgkmkhx +rpspvmxkfqtknqpbvcmb9zrqvkzgszbkcone21 +5oneklx3 +fkjsjg5seven75gjkh3 +eightrccsmczqbn92eightcxgrmpsljztwo +pktwopzqjjmsixshkkqkkxglbzqrxr6 +4mdfqlone43nine99 +34fnkjkfbqfbfmnbskfzvspgrslljmmseven +89one72nine4g6 +two5fjzmceighttworqjlsdt6five6 +pneightssjlhtzqvvzcgxjczqb8 +9jnlthv2djkxqgcfmlzvtwonek +fivesevencqmhsd2zdmld +fmnmqbnhkg1nnsnsdjhfivenvvztkfournine +8zxcqlrftmvvmvg1ttcpclfvjggblp6four +prlrhh8sevensixthree +kmdnxq3 +653 +l6vntwo9 +lmkqjnxjrqqcd2two +vpfvlklftthreevdnsnvsix2 +33ninembqcjndfl6 +two6rqvdctwo +521onethreepsqbgd1six +8k +qxqhpv2sixfxzlcdnfhdj +six8gpxkmlqvsvx2eightfour7 +dxfrgznlvtsxj2fourdzdml +tnjfm2onetwo92two5 +eightfiveninejncfknkkone825prnmmxzcdp +9sevenfive23 +sixninelclnzpdhd7vrfvsksrnine1z +sevencqsleightone6 +nine9seven495eight7 +xvf6xdsrlqcchrzpskgvfiveseven +three8t22eightmhbsfnkhqdmsqpfzhthree +6oneldljnzdsevenbvkcmgvhstqslblgfxrkfour +9ftkbeight6rpf +8lsmnpbdt6fourgbrfhpmjgkrlc +2five1hlgtjplhfive +ninesixhqdcsxlsm4991cmlmrkgrgqmdbmtxd +zznhdgkcrq21three +qdgtfbzxh1 +loneight7ninesvjgvfsmfjd +3mj7313gbxcdcnmvjzqkbg9 +vnxknklscmhjrxnzbp9qzfiveeight +2lxbtvthreetczjsonepjmrsflhndone +jsixbqxkjlzxone8onefbqgnhjmnq +fpsbqpx5drptgkvtwothreeninexcrm8four +rhlcnnzvcone484three5 +6threefive +sevenrkldjeight1 +16744qgmmpxxn3nine +xq1eight +sgrfourc6grhd +9three944six5rnzj +ztjfqjzzsq6sixsevenseventwosbztgl32 +eightztmtzkmjdvjxhrnbrph3dsdmkrndd8zflhmtpx +two3onevgrjshfl5mkdxmdkkrtthreesix +srkgcdmrpd5 +4ltngqjpt2five +seventvxkdvqlbd3eightpmjpk +3three5 +nine5d +mrrbl8 +frvtwojcvppjbtpp3kpzzf +eight4oneonefour +nineptjfjfourthree1six +jvlmgcpxgckgzjpczfvjkthree2 +twotwoeighteighttwo7 +cbpf5threedsvlvxfcx3fourone9six +17seven62sixjklrjqphfcbvmnscttwo +jsix75qcrrcjthz5jnmxqsfoursix +sevensrkcschst2 +two7nine888fourthreenine +3threethreepnx5 +sevensevenvlttfbxmjg1five +233eightmxbmdgdthgxgv +6three27one +fouronecqgspprhgt8rzshnskmn +364dclhtvrkptqlnmjkpkpjxtrfm1seven +3cdf61fttxmkpbh63c +eight1dpdmptdnineeightsixeight7rvzz +four8sixsixfourldrxfszpnlcmkjxnsrqrone +krhgrd2ninesixxftmtq2sevenmkld3 +79onesix +twozjgx1qdznxdgzpzghqf +rvpfz675fpzvmskq6 +dnnnfxcrxhninefourjgdkprtqbv63 +rhndq8zvftnvqm8 +5onetvnhptcqlm9z1 +49nineqgsjrz +28kbcjbkmrvqninetmmqdjjhxoneprtkhdsllc +threesixonenine9 +threevthxddrxzqbcninepmfczcppskbj7 +blnxkpbbgndjdsx6 +vloneightninesixsixchp3eightnine9 +srgcvgghjjsixgsnqmlfive672svfb +glkzvd84 +vr7two24threethree +xlfdr1fivelfxvnjpz +3frsxgsmzrh7 +4one6hrtnb3 +eight44fivesevenrhsxbfbntseven +9two9cfffqd +pbqp3ninegqgxvpkdtjnqsb3zshhlxsrkrvjm +7seventwothreecgbbvqftwo +3h +7bgfrqgmqsix2nine5xgbr +zdkqfshrthree4nrttmzjb2one +one15 +2sixdx4 +128ninenzcfmbgq3sckqrcnkvgthreektk +seven2zqgrjjsq1four8sixeight9 +4four11two9dszblknpzgrcxbsmp +hcxcxjpndpeightfourf82three +sevenrpsevenxzcrp18five +rcklcnqxgbtszdxseven6 +znbkksfjtltngpdgsz2grsixxszeight3 +59cvcvfourvcvvshxone4bqnmdpr +sevenseven7 +2sixone9gkzkxone58mpvpsj +2bhhzpkjvtbpqf7mkrskcqfourdbqfkkxzqbk +three6fourtrqpjxzgfones8 +oneeightfive19seveneight8 +hhjsqdqhsqdvkmnqeight26scjgksix +sixfourfivetkmvpdvdkfhvfourthree8 +6264fivendcxsmjdninetwo +ssixsevenfmmzpxddc4zbvcvb46 +tqfgpdsqccdfvhjtwovsnine1seven +ninesvdlpthree29k +gnoneightqpsgskpqsjsmfiveffzfklltxthree7vf +fourgvonelxrqbddksnqljsmqr18four +four18threethreeeightnine +nz7mhblpprsgpg +nine3two5glbgtkhdhv87lptxgnbsl +5onetwoone78 +6fourtwo3smkssmcvpsv3five +ps7xxfxmqmvkzjtwo +nbsbfqqqpt52jvphpgp +zgxvgqjklftvtrmfour2twoone5hknxfkr +4two6sevenninehpcpbtvrgc +seven4one22ztmlsc5six +rvtlfsktxp7four74foursixlvg3 +threetwo4seven +kdnstttczthreeonetwotwosevensevenccq2 +9sixqjvcnxkvbmqrqvsskf81 +3jrdhvjsknddqdgzfmhqcdmkskxfnxvxlqtp7 +39brqqqlcjqk4one +onedddpmznxcd7three +415nineonerbpvzxszfone +fivekfvsxdstm8 +47sixcdsstnjldeight6 +6threerhtchlzbpssjqdhs22seven +foursix9 +mqqdrpzmqrsixqsdndm6mbgvkone +czreightcjlznine9cpdtdhcp +298onespqbfmmm +39onefrfkvknine9 +7hsdbsbfrft +shfpxrfrb45rgnpcrqdtsonethreezcgngh +zbeightwobtdhr9 +9lone2zrbfzqthzkrrnine +lvhlkdzqsvfive4bpqvkdmscfivem7seven +fcknbkcqrxclntnine445four1 +five57gnsfiveonejqtzkcjmzp +threeseventxbszffourtwokztjpcbvv3three +mspeight48fourxxvxmxc88 +one67 +gkl3three2mcljzvkpx +threengltpjhdhmjr6sevenntcsqqf5 +meightwofggvmkr7six7 +twoxjcbfjjcmq1kf +four7mseventwoone64 +7hnhhcjnrxsevenffmjlvhnjvjbkgzqmhmonesixhhczncfnhbgsg +hppxtkvseven8g314 +fivenine7sixfivesixlmnlqcg +4gdzjjjsvkl5sevenfour7 +bgkldxbvsqtpdf17lgvbl4 +3zfm +dvoneight4 +three1eight1xpmvzlfiveseven +5ninethree6dvq +69lgmqxpmdxtq +6one8xszfmzfvpxmhv +three971 +tdklrczbqgjhhpz2gkh92two96 +6lrxbnvlh5kqqzbksixmkhfkc +5ninetpqplfour4 +eightgjfjqbzlht742 +lvjtvngcpl2four +nineoneeight9twofivevpfhtkkdmzz +sixcdncmsrzzt97five8tqjthree +tnchfkdmfzjsonesix76 +fourl8ninepjbmkxzdsjsxdj +twozqs7 +zgsggdkgkpdlr5one +zzdkcsevenqggrdzrcdllqqpdnrbsevenvhsfnr68 +5sevennine6t +4rlmrv +six5mlgsevenrflgjfsn1lrtcnhhsc7six +6ff1six +nine87eightsxrqxj +vnvsfqllfbh6fivesixsjpgzrvdzb +six5twoseven +5fourthree3pszxtfivesixtjfdnrxt +seven7jmngpvqnkf979lkgzhbvbltztcsqhr +fmrjztlfsqrone88 +ggjpbpjmdgsix9one +76fourlnjlthhnsix5qqjsxxznr2 +1ninesevenhlbeightfour +1slsghqc +five4dhdkdvrcpvzcckjrrrjfsonesix5 +2lgkbfbbfour3 +5lgkccrp3djlrhzdxck +5kst8fourkljsstq4fbvjmfznk2mhd +3ffmlqrxnc +khxq29 +gxqbkhrone22371lvfsbdvgxt5 +ntfpgz1 +mnbvfqbrgncqlgk5eightxnjgslfqq +four8txcjdvjcqxzdhlthreezslht +933fiveonetwofkprnvkd5 +5pjcpqnqsmfqbtp85kk +6hcvfgzpl7six61 +3fzpgdtxpntlcfptlks4 +5five8 +two2mfgrdn56sixfour +llrgftj52tpdxttlnqzpzfsix +twothreeeight2nine1gmz4five +kgmjhhxl3vk55six32five +twotwo2ninethree +nine6dgxbvljkpcfourrrc28three +one1rspjbqx +7lxmkdvhhseven +sevenninethree51 +fxbstzjvtffive185five2 +one1fivefivexhkngdtnkrbkone5two +7skdzgrpcreightwokq +6znrpdhnine6621four +xsztwo2gjmqtfqfrjhtzjbeightqhgzbpcdeight +one597pbr11 +lhnlmjml2onetwoonesix +86fourdgnbvgsnrd53four +2dnfour4mhmkxtlnrjone3ninefpthhxn +1m +8pmszqtgzcz44four +bplgrtzvvqhjgdgfourqbt6one +3three3sixfdtqkmsnc6 +8fsfthree2onebjntcx7bsghgxphp +three2779sevenfive1zt +seven7gxntwotwo +1tmknl +4fourckhl5pvkjhzqnxp3xzjzcrgbdct +rzddzgbeightxxmgspvfprpkpmsixtwothree5 +8xdqsjqxddhxqvszjjqbsqgpkfour1dxckbnsgfn +582jxgfivedmtwo7 +drsoneight61 +9nqhrrtqrsbbjmlpftpggkmsvhd8 +oneeight55four7 +lkgfnd9leight9sevenfourpcxr +3fourmtmsgtwothfgbxcs2tvvzcsshb8 +2onehtgthreexfnbfrhnhrpq5six +threetwoonen3fivedbzbkzqdxs +gjeightwofourqonesix5nine +54oneights +threesixckkpbcqtgjninellm4dhvc +sevengnxhjjmjbstvlp94sevenfiveqprntdkmn +qchrbptnr4sixfourdzgfxkzsgq55 +lzddtfgthreefive26 +12nine +cfvscrfive6seven +kmvpjtmhhv2one8 +5eight342 +frfngfnx1ctxzxfztptxs89sevennkdvbkq4 +vhtbh1twopngjtq +75kfdrjsnvccninethreebqjh +rjgbkhrd3three8two +psgdspjqqqmd5cdpznxfrsshk +7fourqmtbg5hrgxrhrm8 +threeonepdgrrpblg2xhpqjrbppfive +sixjtfzlnmninerztjlpcjpcxrj3ms2 +csmqjmrb53sevenninefourthree +onetwo423 +c5fivethree86fiveeight3 +2pdpllthree53dxbmmrvn276 +onelnhg4hlbsgzhcm1seveneight +stwoneeightpqzflflfmvmqone7 +86fs3zzsfrn4 +xtlzjxthree9sixtskggjtzkt2 +brjnsc7sixlrmfgzdgktsix5rhtxt +eight7cb +hp6one89zpeighttwo +threenlgmsfzn4 +1msjbpksxqmfoursixthree4three9 +zkhkpttm5seven +p8 +frjrvnone9two +5sixpvfmvfivevtr4 +qbptwoneqcdkqqtnmfjrpplseven13one +5four2one891hvnl +nineonethree1 +beightwo55sscfxvjmqrbcsix5five +sixseveneight82m8dlg +f5six +fivedsjjnpbmgckfpvbfqmhd7 +eighteightthree7nine1four8 +nine2cnxqxvlzt7frsbmtfcfive5 +one8eightfivejdg742 +twoone6 +jqsrmzj1seveneightsix +two7five9rfs12threejmg +rjgggrmxkzrpjmtt4fouronesevenninepppdtd +257sgqvjghcneighttwo8five +threepgshzbxvpfivexmlfg176 +lxlncztzvdzvx1hmjgxkv9twonec +ppfftlnksfmbhntb1twoone4qpgpxjrdqf +tdrthree5gxfq7gv +fourmfl8zl +ckhf9cvcghxj3 +vcnfvsvvrbninemf3jpnbqdv +37ztslhzzlv6blm86z6 +glgsgtfhhx7gpxfnfckdjhkxsfourhhv +twoqmtzzktfjs9vpvpfqxtlf1nine +two8two6twozfgvlrdjj +seven7k7pcprskqtp5seven +1bvgceightoneqvhppcfjsf +4qjonekhqjsprx +rmeightwosixhhthree484 +6two6five6ninefournine +one2864onerbcfdfnr8 +threesixoneone3mbz9threestddhjz +rprmjtmjtmfourzpmfqptwoone533 +one6foursix +fiveeight9njclrmrksdqonefivelvc +three1qkrvgcbnxfour +5ssqddjjmmrkjzgtklztpdnpd +four7qnnfnvgkzlldmcnnine88 +four58fivesevenztqcxrzzqhgjlzt +one24onecxxlzllskdtvsevenbq4 +ccjjht34483 +8onefourfour8gqh53szjqrdhzk +18six +8vvbqzhkgz84four318 +mzxzsjfour64seven +t1 +89sixthreexhtbnlcfnthree +hdxqjnine5xp +seven542nkngvnndrrlrmfbxdntwonehhc +ptwone6nb58nine94twocmkf +six64ninesix73seven +seven91sfnbjsccqdtzgleighteightwovqr +vkcvdone49fourkbm1one +9sevenrg94 +foursixsfvrvhgvc1qvjkj +fnvtfttwo847 +vgxjts7 +6bxjvpksix5 +qxlpjg38qkmxfivesixeightqcffhsxnrk +1mgjfrfv8onetwoxrscgjlcdhnine +rmpvtfkmxnzrfsxtcdj36one +569fourfivessrblkq +threethreezvvkdjzkx5xjxnlglfrt9qdkscsdf13 +qcgd4cbrjprvnineqtfcxnninethree +6six9fhhgnvfghsix +ccjrrbkj56zqzbsf797mxsq +3ddqxrm6one +39four2ninetjcvfzhmgpsmsxrjjseven +fourtq95fourfourfive9 +threemz96onezsqjzbrb +txzgzgcc8threejthree1 +four4ninethree6cqfbfffptwo +one3kntwothreemzklllzfourcjlrnmb +sixone9fivesix +8jsddhfppj99 +5threekmxdglktv +onemxgbhqzjtgcxdmkr994 +2vsgrxcrjbkkp15 +2two7rfvfkzzmpdgqtfourtq5one +ninecqveight5tntgtm37 +38ngqrvhjkfmcl +2fiveeight5 +one5ckh4jtjcqcjr54bphzndqrvnine +8bnine1fourone +nine1sixpbckqsixthree +one7zllzvvgklbkgphtpv +6fivecgrlfcheightonebbonetwo +dgchmmqfbzcjcnpvttcp6 +1seven73ltpgbts +1xsdvdt +qphknjcb4lkzcqdghd3threethree +8eightjxplnt +six5fnnrzghlnjsevendmpnnonethreejvmzgkck +threesix2jjseven +8twotkzfbzbbfive +6onehjqdvpbbmgpnzjjbxltwotwochb +seventhree5four7vgl +seven9fivefive7lxqsldd +xjlkbctseven1 +5sevenpslbmmqnrnztgmdtkzf9gbs1 +bsndznhdfjeightonetwo58 +rxzf7n9vb +4pjhkklkhvsix8 +one11fivetcnzcpzxcssevenseven +one6eightonesixeightnineeight +7xgkhtrpmtwo6five48six +dgs4 +pdb1gtnxthxqeightthree2njhzjtnzfthree +6bstmrhdhhtgvfbqjq +xt68 +1seventwo +79qtjd6 +rhcrhmtmmxcnbjdhqtd7cdblltsljntkbcqnfrchbfbkhclseven +hnlhz15six263nine8 +gxfvnsdqjdsoneccthxvtbxxzqbzplfldxx9 +3sixgsdt4ninefivemxtzzqrztsix +onethreeninethreetwo6pldp8 +n88 +sixseventhree5seven1 +jzrzbhvvpg881 +niner6sixthree4 +4sixfour9 +twodm3dhsxlvvrghqbvfpqvqlvtxdjzjhqvzmb8 +one67three17eight +onefour1 +sevenseven5four23 +qcvddc8rmmmffhjvthree8 +68fmf6 +xcn5 +nineqbqhkxhrfourfive7lftzls +zkkntfcrpthreefive8five3 +ngnzlh81two5 +ninebkxxrvrnh4five +7327sevenspjjxxcxbzgsztgnr +7l7ngrhkvzqftmrkd +2rbthreedtdlvgfthfive +onenine5dzvznlkht1zfnbspkg2 +33tpfdsevenfour8four +19four5 +twotwoone398eight6nine +dcqgn86sixglgbxnp2 +six9vksix5273 +fivefourseven12sevenjmdhpjpeighteightwolzl +1fmqcg3lponetwo9 +tlgbv6fqpqbxskfdmqfour7 +9hqbtt6sevenfour5pfgjktbjhzr +ljlfssmk8pbmdrzd +ffmthzmtwo67fourfivethreefive +kjrnrgqfseven2mtcgtwo +hkgeightwofiveeight3rdtxkfvtwoldvxcdm1 +seven72k52 +xnqf8two7 +sixone5two3 +5eighteight5bsxlgbrpjh +dzgngckszf8fivekpjdbfl7cxprlclfiveseven +threesixthreepmglrtrvxkrzzkq59 +fivenine1eight7nine +9mljfqfjxhzone548 +7soneightpkz +6qq64gfscshkthh8eightsgcmpstwo +dsrvbxvgjf8 +7zzndrkdkmeight3zhgnpgfmrnine +7sixzqmthree5frgxzlkm +3threefivefbplhjtwo +rspdqldldtsr7seven7tzzhcbghtr +1sevenfivejrlzn +threeeight3cjjmr5 +858shrxcprbzjpblfmqpxxgqsjcvr1one +zsttpjninezbkxnvzcdhxhprmrxnrqmvl9 +eightfivefour99seven9vlchs +four1dpgsptmvvqsb +rzbvrst5rone5 +7eighttwo4sixthreebgpskqdkq99 +vskgbh1pj +4vpsznm4nine +onemplzkfckh7pdlqrbeight +6fourkrxslrpqdsthree9eightczfkk +2xbmjgjfour5four4four +fpckvttjznoneptkmtbtgsg12knbzkxgsr68 +twoxmjmqdfxjptwoqzpdcrcfkplklthree3fourfour +8sixnine +l6 +rpskpftttthree2bthreeeight5three +five28fivedpf82eight3eightwoqnl +lgdgpnrn7mklfpcggninefivejvsix +vtdpfp21p +fivefourlnbjf8 +bqnx98sqdpqeight1 +sevenghmdbgvninetwo57 +jx9onetgbjjvhgqvqrstztbthree39 +ptgxlzrp858jkdzgkthreetqlr +2threebmjmzflthreebrzfxrfive +twoonekrkkbbjrfdbpx9 +43bf +eight5five1ninep8three +fournqvnzhklffivexbxpd5dmshsx1 +fournineeight572 +zx7kqgtqv +1fivethreevkzvnn9five +5rjjcz3sixninesixkrjnblg9pnnhzkjd +97sevencplhfngjpc8four +onenjgphpfqr8oneninefvhzcpmdmbsix +threefiveone2snbmscbmkxlcqqqcggflvcgjrnt +pzzhl5 +xfour2mltvkkclcrzptdfldgone +4llllgkdft1sdsixeighttsbxtg +3onesevencrrkrdlbg5 +7eight6fcfive +xbpzhnp6threetwodflsfr +lfkjqcvvlcpxbvp8dnnxrjzklj2strggkjxzkncs +8one2xqjdnine +ninecdcql828four +pbfg1sbfxcjvthreesevenhzdtwohnxdoneightsb +1fbcmzflvkhrkkj3veightonetwo +4threethree632fourzqczbxz +1sevenfour38 +mlrjnpd7eightgnjnxhgz5seven +fiveone9 +two78 +9683klkrcvjz +nineplcvqlvrninenine95 +148hzeightwor +ns6fivemzqp6 +58fourxqsqdg8 +rmjrxhzbhnzn6jgpgvjtwo1hone +xhzphxb1xlqkktxtljmrfour +five6txgsfvnxqbnxljrblgnvc +1threelzq +4gclpljthreerqpbpdhftonetwofivevqm +six5js +twobzktcpscjlfbttxbbtgqvrldrksbvxzrxjffh9 +five1142sixninetwo +8vxclrfive7hxvlgr +62sixxpnbhlhmnlgctgqnqppdczm +9zvfzssqhhjqleight3ncm4two7 +cvsix7cts +eightqnjbnflkqsmdcqrv299 +sixjqlmpkgcmcmcp6qsdpqpdseven8eight +79gnncbfivethreevgfscv +sb4gbzcvtp7foursmtdszdrg8 +fourthree6546 +2nzjtvpsr53 +9pc +nine3eight25eightmeight +pmninezgk5nine +xnrthreeseven9threetzmg +7one5gfbn2 +vtsqhzclv89fh +6sevenfivefiveeight1 +vxcnbtnine8two4tvttnmfjntxmxnqgbhhlonegvkpgs +peight5shvjcng2 +szlpphx277nineone +bhbvtsjpsflkcmktnpqjlzsixhhhxl9xtkbvmszqseven +nine3five2dmgjkbctnnnsix +8threexgklkrz1 +fxfrqrxbrkdfivepstvtqhlrnhvqbtzvfnineh6 +five6gzcdrjxngf6zhsvxgeightninegp +kgqcnddc88eightonetwoeightxs7 +eightsmgmfourmdjzvtd7 +sevenseven836 +sbnrfqzhk7eight +1hkxbb65two7mh +dkczbhqtpvcqfrbmcdcrsixsix37jlqfninenbqmtfzcb +zcqrcpbfttmslbssbpklfrcngmszvvpjqf4rlvqxlnchrxkndbrtxcnm +7kxmzxbhdqsix8 +13 +lqlbfzxzfkxsdbz3six6 +sevenfscdrdvtjeight9threeffrvxdbc +fivebnn246dlbbhphqqgm +hrfqnlcvltfour2 +vtjfour3five4jqtwo1 +fivejkvczdmqzmfourthreetwo6fourtwo +ninesixsixsix3785 +six3sevenninebcvdltmcvgn +rdjqktrmtwo8cnvzv49twoneppp +eightjmcc4onefive3 +3mszqhnzqdhbbplcnq1tmchrgcltnq +sixsevenfivefour5ninesevennpjqzndjx +15fiveeight1fourqprkldhs +one1rbn1lnmdmdf7sixbjxv +pseightwo3jrvcfiveninefive +rzvjn16 +55eight7285ninedf +ninedgone9 +1two9onetwosix6nklsjdbr +9four8xbgnxgs4 +prqkonexszxfpqr9eighteight84three +xkgpnzsptwoseven1foursix39 +ntpkrjggj2sixkznljqzljonemvq5four +4nineeightsevenhgkflgvgqs +zmchljrjpxoner7tgxjdkmcctzrdcrqvkmlnftvm +439sevensix7 +91xkrmztdbpkpdxtrzkrtwothree +tfive11l +htxzbxmlthreesgmbh4ninenine6onefour +4dtcxqrv63glbpmznm9 +3shdcdzzqld4sixfxdmnmjlz7 +8strtbonenine7sevenpcqjvqclcc +nccnc1vjslvtddgcddrfcztqbxvxdnineeight +826nineninelpvnkxzfive3 +7llqfvftl7 +twobdnbnine3fourbsrvpkqsdjxcvk +onefivespnhqrxjzmfive6nine5 +9lfpchffgxthvheight +brqjss6six8six +sevenrfsix7sixfourfourxbjzvtwo +cdtwone863 +eightzvn3 +8252nkkndmhpgtqnb +1pqmbdcrfour4 +263vmbrqqdtrn45ninesix +sevennine4ldhlmdnhzjqksbkrg62 +eightone5ffprsmqfzq6 +fiveeightnpfbdtdbhtwosix11mghg +2seven82six3one6 +81five18nineonemmbsj +4eightbjjjqnc +sevendstdrhpfxfnnhrddppms9 +kgtptmpfhk4 +seventhree6hllpmnqr +cpn38vlpclqzqcgpbdmlbzfssx +96fiveflq +bqcxmrpzql5vxfnpvtwo74kdhsvlkzz +pgxqcskz611bzkhmnn46 +fourfrl7mxvtkthreecfkpmxqlxhdf4tcgrp +3dhzm +58fivenine1nmhjdzlctj8fplnhmtwonexh +one69 +fivethreenzsgqpsmhronetwo18 +five866sevenninejbvm +fourmtnkh4 +9ninelzqf54 +727 +ttwonentrmkxckfxonenine4mdpjhpkbrfzc +fmsix45fivesix +767klvdthjtwo +pnrlxt6hpttnlp +rbtgqmgmthree44ttvone +cgspmnlsl47nine85 +threell6dqsnn67 +486mz4mqpgkxlmdkp +rgvlcpnbnch7flgrm4twofive +hsevenfourcxseven4three +87fnbcfftwozxnnqmqtmp +3qjfnzhhmxt7 +leightwomtzt36sevenhgcfivetwomskfour +sixsix6nzznseighttflzgcbzcthreek3 +eight4725nrpbxfonetwo +scfiveeight7three +onethreezvxbfdklnhone9sixeighteight +sevenhcone5nineb +dkmmhkhsmnmtonetwopdcx6seventthhgkdx +rskzlrdm2six +one8cstbffccz +eightsevenzkkhlcxhmxthreetwosixone51 +82pgkjcxmcmv11ninetwoneld +ftmhgvdrfxdzrbhqx78 +xlsbhctwocvzcxxsixfourtnvjnhrn9one +6jsdgbtbzsbxvdkdlrdk2btonellsdxzfrvvknsrgml +fivepkblscprv49qdztfjtwo +one59795foureight +five96 +6mqj +sixtwonhjhcjhmvkjndzphgkb7dbmngxbthdbkqbpeight6 +569 +4svnndr +xbsfhvsq22three24 +1mms2nbmlsmpkrjvlz5 +gstwo25ldvfzjonetwo4 +mkbsmtrrxljdrxlnrpcrhjtvtmqbzvkld5zvphtjflvmvhqxzrnine +one59twofive5gkvpjlxczb +c5ktp7sixfoursix +mdlrxxfour4pxfour +78hkbqnggsix2sixnrmx +nine2mnxlh +brvkttkjvrp8qpnfgfjhpn +threeseventtpsmm2eight42 +grrxjpcxstwo19ninek6 +kmprxnf1seven8trnb7 +onexmrjpkhdvmfour7seven +2fivetncrt +four5qpbmfxssixbjfdcdsixlcjmhsxx +two87three43 +hjkrr5nxsczthree5bskmeightln +18threesixhjqz6four7lcrrzr +onezfourv1 +rglmnronesix7sixone +6cffcmlfkfbqgfivegkxsf4 +3twoeight3 +six4five19rpjvktvxlqczkcxttssgxcztk +7threethreetwospzk4 +gkhgv3 +plhsjbdhchzzhztdgt4dfkxeightngnxtgqqrvgj +sevensjkvk15qvpckmlh +znvljxmvjc7eightthree66fourrzgkvrxb +72pvpmlflqj4two4klbjmbrfxrcs +mcpvlfpb39 +3sevenlbfrflzeight +126 +78one4hqphnvntqt +9rmpzrfsthbfourthreefive4d4 +one7eightthreecsxj24 +ffmk2gvdngdjxzgtwo55275 +2threefour8qtlhnj987 +gxslxqkf4gmpfpqtvnfourf +3vjmbtpvdzvcpfour8bsppd6 +lfpzvmmnf8six8sixrvmhmg1dcqbc6 +7ppssvcpkpvvp +48twoxgndlgkfzqndkcdzcnr6hzb6pplx +sroneight9lxb6sixfivenmmcnh +tnpdqnqfgs7bhhpponesgmbvrmcsixglddfpbpxvp8 +twogsbzkvslnmfzbt3 +jjlqpfhthree524eight822 +six246fhhczntfvdcxjfqcxzmgdn +6threexgs7 +njxmonehnzjqfnsgbf3rmmldfive +one77eightxgdxghzrtgzddr +ninerxqzqzhjxf5 +4sevensix8onept89 +4onefnnrkljbm84rdeight +ln3253 +ninekvzvmhvmnj7fourchlfggglbcrjs +gdhrt7tjmgmqgcbblx98six +ninefour7onetwomcgjhgcgdl +fourtwo1fiverd +1three7twosix +sevenzgpmc2glhbfcczzg +3fivesevenfive +cshghdvkthree18 +19four5hsnsjkmrrsix +4xcqlfvnxninefourzzhfzkdfdg6mfmp +tqrjmt9zsctcbkpdlkqd2 +2zvpsevenlhzj86eight +xkfzftj5nfjlb7onenineone92 +9bqkbsjccmeightninefmnmfour6jstqgfcfdtqr +ninexlqcltkmdeight64one +7eightfour7two +three6tflgzsphcpbqgvmqnvn8 +threejdlgm8293three +pppm8dzvd8onefourtwo +ninetfkqhmckv581 +eight91twofourvzbpmf +1tgrgfourseven +phpfxdrlcjpshbrhrktwo2kzrcngmsmdfpvlmmbjzbrrxznkv +57one8two +fourglsthreenbzdfddhdh3sqkh +2glpbhskt8526s +455dxvmvjhh1skbrrf9ck +ninez6 +pdcsjdkc4nine +nineonesixsix26qsmkfctbhx +five9two +4ktptmhxfivefour5svlfvsgjsvgseven1 +eighteight8ninethreefourlqhln3 +seven3hffspxvklheightrx +eightjqjhzvzsixfour5llnhdvmf2 +5lptnqzmk99kdqqqjmthreeone +rv1 +5sixfive +cninethreeone1sevengpgqdnpk +4vphpshpsqngthree65fiveeight +3zkvgntwo3sixtwo +1gqxgxbdvmrgd64 +threemctclrrzvqzdnmkpgffive3snhxseven +dfngrsix5nninetwoneng +7ctbp7hhgtsevennine +9jrnsp3threehvnzn3 +48onepxlrpf +threegrhsffmlv5sevenseven +two7eightthreedmsfeightsslvfour +xfdljlbdjckkdzczr362 +four7mfppkmklgrmpmt91threenplqff4 +3cszpvddndjfmszrf +qoneightntdzfsix5lcz +fnthree1 +two4sixbmrndhsevensvxddjbdgmgdtlncpzph +9ptssvrgv +twov5 +4three2xqz3 +xxqrmhzdp2gnxscfourgkbkgntgr +2nzxdfxcvfive +sixninebtmtrvpmfnpdvceight3 +four8sixthreedsm9 +9blpvdpfqkghvh +3oneeighttwo2tflmpdjzq +fn3oneninesix3n +jgcd4qnbbxcvjqlthree49bfchjz1 +glj8sixdpbdpbqhh1rvgmbcqx +threeqfj66 +5qvhpfjkkbhjbkkzrlgfourlzvrvpn2nineq +3btvbbpvpl7ltf +bfxmkcn4sixfourglqjtmzlgj2eightfiveeight +twotqfpfive3eight +3threebzmcvtknthree8fiveone +gzkrdr1 +4cgvpfljq4szjk2bxlmn +tfdkhxtgj9 +one64llx9zjznbtxphn +7twoninenineseven19qjhhjg3 +cxflp2two2eight +vrhlzfsnfqzfqf3dcvzhbtpdkqdxn8nine +bsddhtzbpgn1llfcgm38 +one66twofddhjrkxjssixkeight +hmsevencnltvthree68twonezmc +3fsrrn +twofourseventxbcqzz8p +4121knflgt +tplkfivejlvtfm3tmcgsevenseven +vhhfhsfkqqeightone22four +98sevenfournine +nineone199 +2sixnbvpfrdvcctmdzxl +8gfbsrmhpnsclvrntwosevenseven2three +3dnhgfvhdffllnine +3frbnkjjbhrsixonesevenxph7 +five2gmxjthkksfiveonerj2nine +bjkvk6three5jtccbcvntwothree6 +4snlgnj6ctnzvqmphkzdcj335 +5bhhjhrnzftwonine4 +m8sixone7 +twomrhtklhdsdsglpncmffcqhthree4svxsln7 +sevenmzqn2hstdtfivehjhone +vqdhc8twocztspvsdpskgxtjhgk +4fourhthdppjz +446gfskjqrlvnqbm8xpnvq1 +jzcdttwo8xggone8fivezkzrjzn +gqfhjhkf7 +ds51sevengpjjnmxtdninetwo9 +twopbqhjnjpkl8mdrkleightrtlrhqn +3seven3fkb9qcrfkknht8sevensix +hvzrpbbbeight72jpvkhkjxgvxqjfqfour +eightthreeonev4vtpnbpfzch1one +sixdlds5twothree +eightjtrpdfxvdlkqmrrbxbc6 +5mtqkkxsqf78nineseven +dkkrkxxonevjqdthreen21ztnzlghmttxmblpp +ninethree43mrgng6jtjm +fiveg2three +6prj9four4rtm21 +one2vgvklpcqnxssjbone1six +8glktlgcfsevenmkjvone3dgjjfkd8 +threeone6ninefive7three +zfv2c2four5one6b +qxtbbtwo7jrdgxlcpxbczxhnpjthreetwogcfl +vfhgqjfqfc78eight +1x5 +six5four1four4 +2fiveshtds4oneightsjg +962seven58two7 +7mrtndknxzlzdkqcfjxgz9f66 +fqckxpqrjk8eighteighttwo6fivejps4 +drvglmnine7three8one7twodxtr +mbnfjkxptbtjmgcrtkhxjvjhjnine83mpnsixfcmxcbnspx diff --git a/src/main.rs b/src/main.rs index da2d3e5..af14dd8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,4 +62,8 @@ fn calculate_calibration_value(input: &str) -> i32 { fn main() { println!("test value = {}", calculate_calibration_value(TEST_STR)); + match std::fs::read_to_string("day1.input") { + Ok(input) => println!("real value = {}", calculate_calibration_value(&input)), + Err(reason) => println!("error = {}", reason) + } } From 51f73a0184274e4f96a159d6dac5e752aed9f9fe Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 2 Dec 2023 18:28:34 +0100 Subject: [PATCH 060/120] Refactor to prepare for the second star Parsing from the end no longer is the best way, we need to work out actual words now. --- src/main.rs | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/main.rs b/src/main.rs index af14dd8..14fae1a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,30 +5,27 @@ treb7uchet"; #[derive(Debug)] struct Line { - first: Option, - last: Option, + digits: Vec, } impl Line { fn new() -> Line { Line { - first: None, - last: None, + digits: [].to_vec(), } } - fn visit_digit(&mut self, digit: i32) { - if self.first.is_none() { - self.first = Some(digit); - } else { - self.last = Some(digit); + pub fn visit_digit(&mut self, digit: i32) { + if self.digits.len() == 2 { + self.digits.pop(); } + self.digits.push(digit); } - fn value(&self) -> i32 { - let first = self.first.unwrap(); - if let Some(last) = self.last { - 10 * last + first + pub fn value(&self) -> i32 { + let first = self.digits.first().unwrap(); + if let Some(last) = self.digits.get(1) { + 10 * first + last } else { 10 * first + first } @@ -40,7 +37,7 @@ impl std::str::FromStr for Line { fn from_str(s: &str) -> Result { let mut line = Line::new(); - for c in s.chars().rev() { + for c in s.chars() { if let '0'..='9' = c { let digit = c.to_digit(10).unwrap(); line.visit_digit(digit as i32); @@ -67,3 +64,24 @@ fn main() { Err(reason) => println!("error = {}", reason) } } + +#[cfg(test)] +mod tests { + // Note this useful idiom: importing names from outer (for mod tests) scope. + use super::*; + + #[test] + fn test_line_single_digit() { + let mut line = Line::new(); + line.visit_digit(5); + assert_eq!(line.value(), 55); + } + + #[test] + fn test_line_multiple_digit() { + let mut line = Line::new(); + line.visit_digit(5); + line.visit_digit(3); + assert_eq!(line.value(), 53); + } +} From f474cc0d748134c503eedb0200e07e79567fd8c3 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 2 Dec 2023 20:50:13 +0100 Subject: [PATCH 061/120] Part 2: More tests, more structure, more rust. --- src/main.rs | 114 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 28 deletions(-) diff --git a/src/main.rs b/src/main.rs index 14fae1a..dd2495c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,6 @@ -const TEST_STR: &str = "1abc2 -pqr3stu8vwx -a1b2c3d4e5f -treb7uchet"; - #[derive(Debug)] struct Line { - digits: Vec, + digits: Vec, } impl Line { @@ -15,20 +10,32 @@ impl Line { } } - pub fn visit_digit(&mut self, digit: i32) { - if self.digits.len() == 2 { - self.digits.pop(); - } + pub fn visit_digit(&mut self, digit: u32) { self.digits.push(digit); } - pub fn value(&self) -> i32 { + pub fn value(&self) -> u32 { let first = self.digits.first().unwrap(); - if let Some(last) = self.digits.get(1) { - 10 * first + last - } else { - 10 * first + first + let last = self.digits.last().unwrap(); + 10 * first + last + } + + fn match_digit_word_prefix(s: &str, at: usize) -> Option<(u32, usize)> { + static DIGIT_WORDS: [&str; 9] = [ /* "zero", */ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" ]; + + let mut result = None; + for (digit, word) in DIGIT_WORDS.iter().enumerate() { + // println!("word = {}, word.len = {}, digit = {}, at = {}, s.len = {}", word, word.len(), digit, at, s.len()); + // println!("s.get = {:?}", s.get(at..at+word.len()).unwrap()); + if let Some(w) = s.get(at..at+word.len()) { + // println!("w = {}, word = {}", w, *word); + if w == *word { + result = Some(((digit + 1) as u32, word.len())); + break; + } + } } + result } } @@ -36,38 +43,48 @@ impl std::str::FromStr for Line { type Err = (); fn from_str(s: &str) -> Result { + let mut i = 0; let mut line = Line::new(); - for c in s.chars() { - if let '0'..='9' = c { - let digit = c.to_digit(10).unwrap(); - line.visit_digit(digit as i32); + while i < s.len() { + if let Some((digit, _len)) = Line::match_digit_word_prefix(s, i) { + line.visit_digit(digit); + // oneight... + i += 1; + } else { + let sl = s.get(i..i+1).unwrap(); + // println!("sl = {}, i = {}", sl, i); + let c = sl.chars().next().unwrap(); + if let Some(digit) = c.to_digit(10) { + line.visit_digit(digit); + } + i += 1; } } Ok(line) } } -fn calculate_calibration_value(input: &str) -> i32 { - let mut result = 0; - for line in input.lines() { +fn calculate_calibration_value(input: &str) -> u32 { + let mut result = [].to_vec(); + for (index, line) in input.lines().enumerate() { let parsed_line = line.parse::().unwrap(); - println!("parsed_line = {:?}", parsed_line); - result += parsed_line.value(); + let value = parsed_line.value(); + println!("index = {}, line = {}, parsed_line = {:?}, value = {}", index, line, parsed_line, value); + result.push(value); } - result + // println!("values = {:?}", result); + result.iter().sum() } fn main() { - println!("test value = {}", calculate_calibration_value(TEST_STR)); match std::fs::read_to_string("day1.input") { - Ok(input) => println!("real value = {}", calculate_calibration_value(&input)), + Ok(input) => println!("value = {}", calculate_calibration_value(&input)), Err(reason) => println!("error = {}", reason) } } #[cfg(test)] mod tests { - // Note this useful idiom: importing names from outer (for mod tests) scope. use super::*; #[test] @@ -84,4 +101,45 @@ mod tests { line.visit_digit(3); assert_eq!(line.value(), 53); } + + #[test] + fn test_match_digit_word_start() { + let result = Line::match_digit_word_prefix("two29eighteight1", 0); + assert_eq!(result, Some((2, 3))); + } + + #[test] + fn test_match_digit_word_middle() { + let result = Line::match_digit_word_prefix("two29eighteight1", 5); + assert_eq!(result, Some((8, 5))); + } + + #[test] + fn calculate_calibration_value_example1() { + static DATA: &str = "1abc2 + pqr3stu8vwx + a1b2c3d4e5f + treb7uchet"; + let value = calculate_calibration_value(DATA); + assert_eq!(142, value); + } + + #[test] + fn calculate_calibration_value_example2() { + static DATA: &str = "two1nine + eightwothree + abcone2threexyz + xtwone3four + 4nineeightseven2 + zoneight234 + 7pqrstsixteen"; + let value = calculate_calibration_value(DATA); + assert_eq!(281, value); + } + + #[test] + fn calculate_calibration_value_oneight() { + let result = calculate_calibration_value("oneight"); + assert_eq!(result, 18); + } } From 506ae93f80f382a775ac351a203f3af2b82be15b Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 2 Dec 2023 20:55:06 +0100 Subject: [PATCH 062/120] Split into a per-day module structure Let's see whether that works, or whether it needs further thinking later. --- src/day1.rs | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 144 +-------------------------------------------------- 2 files changed, 147 insertions(+), 142 deletions(-) create mode 100644 src/day1.rs diff --git a/src/day1.rs b/src/day1.rs new file mode 100644 index 0000000..768a2bc --- /dev/null +++ b/src/day1.rs @@ -0,0 +1,145 @@ +#[derive(Debug)] +struct Line { + digits: Vec, +} + +impl Line { + fn new() -> Line { + Line { + digits: [].to_vec(), + } + } + + pub fn visit_digit(&mut self, digit: u32) { + self.digits.push(digit); + } + + pub fn value(&self) -> u32 { + let first = self.digits.first().unwrap(); + let last = self.digits.last().unwrap(); + 10 * first + last + } + + fn match_digit_word_prefix(s: &str, at: usize) -> Option<(u32, usize)> { + static DIGIT_WORDS: [&str; 9] = [ /* "zero", */ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" ]; + + let mut result = None; + for (digit, word) in DIGIT_WORDS.iter().enumerate() { + // println!("word = {}, word.len = {}, digit = {}, at = {}, s.len = {}", word, word.len(), digit, at, s.len()); + // println!("s.get = {:?}", s.get(at..at+word.len()).unwrap()); + if let Some(w) = s.get(at..at+word.len()) { + // println!("w = {}, word = {}", w, *word); + if w == *word { + result = Some(((digit + 1) as u32, word.len())); + break; + } + } + } + result + } +} + +impl std::str::FromStr for Line { + type Err = (); + + fn from_str(s: &str) -> Result { + let mut i = 0; + let mut line = Line::new(); + while i < s.len() { + if let Some((digit, _len)) = Line::match_digit_word_prefix(s, i) { + line.visit_digit(digit); + // oneight... + i += 1; + } else { + let sl = s.get(i..i+1).unwrap(); + // println!("sl = {}, i = {}", sl, i); + let c = sl.chars().next().unwrap(); + if let Some(digit) = c.to_digit(10) { + line.visit_digit(digit); + } + i += 1; + } + } + Ok(line) + } +} + +fn calculate_calibration_value(input: &str) -> u32 { + let mut result = [].to_vec(); + for (index, line) in input.lines().enumerate() { + let parsed_line = line.parse::().unwrap(); + let value = parsed_line.value(); + println!("index = {}, line = {}, parsed_line = {:?}, value = {}", index, line, parsed_line, value); + result.push(value); + } + // println!("values = {:?}", result); + result.iter().sum() +} + +pub fn main() { + match std::fs::read_to_string("day1.input") { + Ok(input) => println!("value = {}", calculate_calibration_value(&input)), + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_line_single_digit() { + let mut line = Line::new(); + line.visit_digit(5); + assert_eq!(line.value(), 55); + } + + #[test] + fn test_line_multiple_digit() { + let mut line = Line::new(); + line.visit_digit(5); + line.visit_digit(3); + assert_eq!(line.value(), 53); + } + + #[test] + fn test_match_digit_word_start() { + let result = Line::match_digit_word_prefix("two29eighteight1", 0); + assert_eq!(result, Some((2, 3))); + } + + #[test] + fn test_match_digit_word_middle() { + let result = Line::match_digit_word_prefix("two29eighteight1", 5); + assert_eq!(result, Some((8, 5))); + } + + #[test] + fn calculate_calibration_value_example1() { + static DATA: &str = "1abc2 + pqr3stu8vwx + a1b2c3d4e5f + treb7uchet"; + let value = calculate_calibration_value(DATA); + assert_eq!(142, value); + } + + #[test] + fn calculate_calibration_value_example2() { + static DATA: &str = "two1nine + eightwothree + abcone2threexyz + xtwone3four + 4nineeightseven2 + zoneight234 + 7pqrstsixteen"; + let value = calculate_calibration_value(DATA); + assert_eq!(281, value); + } + + #[test] + fn calculate_calibration_value_oneight() { + let result = calculate_calibration_value("oneight"); + assert_eq!(result, 18); + } +} diff --git a/src/main.rs b/src/main.rs index dd2495c..e2dd68b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,145 +1,5 @@ -#[derive(Debug)] -struct Line { - digits: Vec, -} - -impl Line { - fn new() -> Line { - Line { - digits: [].to_vec(), - } - } - - pub fn visit_digit(&mut self, digit: u32) { - self.digits.push(digit); - } - - pub fn value(&self) -> u32 { - let first = self.digits.first().unwrap(); - let last = self.digits.last().unwrap(); - 10 * first + last - } - - fn match_digit_word_prefix(s: &str, at: usize) -> Option<(u32, usize)> { - static DIGIT_WORDS: [&str; 9] = [ /* "zero", */ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" ]; - - let mut result = None; - for (digit, word) in DIGIT_WORDS.iter().enumerate() { - // println!("word = {}, word.len = {}, digit = {}, at = {}, s.len = {}", word, word.len(), digit, at, s.len()); - // println!("s.get = {:?}", s.get(at..at+word.len()).unwrap()); - if let Some(w) = s.get(at..at+word.len()) { - // println!("w = {}, word = {}", w, *word); - if w == *word { - result = Some(((digit + 1) as u32, word.len())); - break; - } - } - } - result - } -} - -impl std::str::FromStr for Line { - type Err = (); - - fn from_str(s: &str) -> Result { - let mut i = 0; - let mut line = Line::new(); - while i < s.len() { - if let Some((digit, _len)) = Line::match_digit_word_prefix(s, i) { - line.visit_digit(digit); - // oneight... - i += 1; - } else { - let sl = s.get(i..i+1).unwrap(); - // println!("sl = {}, i = {}", sl, i); - let c = sl.chars().next().unwrap(); - if let Some(digit) = c.to_digit(10) { - line.visit_digit(digit); - } - i += 1; - } - } - Ok(line) - } -} - -fn calculate_calibration_value(input: &str) -> u32 { - let mut result = [].to_vec(); - for (index, line) in input.lines().enumerate() { - let parsed_line = line.parse::().unwrap(); - let value = parsed_line.value(); - println!("index = {}, line = {}, parsed_line = {:?}, value = {}", index, line, parsed_line, value); - result.push(value); - } - // println!("values = {:?}", result); - result.iter().sum() -} +mod day1; fn main() { - match std::fs::read_to_string("day1.input") { - Ok(input) => println!("value = {}", calculate_calibration_value(&input)), - Err(reason) => println!("error = {}", reason) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_line_single_digit() { - let mut line = Line::new(); - line.visit_digit(5); - assert_eq!(line.value(), 55); - } - - #[test] - fn test_line_multiple_digit() { - let mut line = Line::new(); - line.visit_digit(5); - line.visit_digit(3); - assert_eq!(line.value(), 53); - } - - #[test] - fn test_match_digit_word_start() { - let result = Line::match_digit_word_prefix("two29eighteight1", 0); - assert_eq!(result, Some((2, 3))); - } - - #[test] - fn test_match_digit_word_middle() { - let result = Line::match_digit_word_prefix("two29eighteight1", 5); - assert_eq!(result, Some((8, 5))); - } - - #[test] - fn calculate_calibration_value_example1() { - static DATA: &str = "1abc2 - pqr3stu8vwx - a1b2c3d4e5f - treb7uchet"; - let value = calculate_calibration_value(DATA); - assert_eq!(142, value); - } - - #[test] - fn calculate_calibration_value_example2() { - static DATA: &str = "two1nine - eightwothree - abcone2threexyz - xtwone3four - 4nineeightseven2 - zoneight234 - 7pqrstsixteen"; - let value = calculate_calibration_value(DATA); - assert_eq!(281, value); - } - - #[test] - fn calculate_calibration_value_oneight() { - let result = calculate_calibration_value("oneight"); - assert_eq!(result, 18); - } + day1::main() } From 05e491f8f57de3ab2c6055ae6c2f273a4f53c13c Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 2 Dec 2023 22:05:50 +0100 Subject: [PATCH 063/120] Day 2, part 1: Parsing fun ... --- day2.input | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/day2.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 +-- 3 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 day2.input create mode 100644 src/day2.rs diff --git a/day2.input b/day2.input new file mode 100644 index 0000000..f50ea2e --- /dev/null +++ b/day2.input @@ -0,0 +1,100 @@ +Game 1: 1 blue, 2 green, 3 red; 7 red, 8 green; 1 green, 2 red, 1 blue; 2 green, 3 red, 1 blue; 8 green, 1 blue +Game 2: 12 blue, 3 green, 5 red; 1 green, 1 blue, 8 red; 2 green, 12 blue, 5 red; 7 red, 2 green, 13 blue +Game 3: 7 red, 4 blue, 13 green; 14 green, 1 blue, 1 red; 1 red, 11 green, 5 blue; 10 green, 3 blue, 3 red; 5 red, 5 blue, 3 green +Game 4: 3 red, 1 green, 17 blue; 11 red, 6 green, 18 blue; 4 red, 9 blue, 5 green; 2 blue, 2 green, 1 red; 1 red, 2 green; 7 green, 9 red, 2 blue +Game 5: 1 blue, 9 green, 5 red; 12 green, 1 blue, 15 red; 17 green, 8 red, 4 blue; 7 green, 12 red +Game 6: 4 blue, 9 green, 7 red; 1 red, 7 green, 4 blue; 4 blue, 8 green, 3 red; 2 green, 1 red, 2 blue +Game 7: 3 green, 1 blue; 11 red, 2 blue; 2 red, 3 blue, 6 green +Game 8: 8 blue, 1 red, 11 green; 11 blue, 10 red, 7 green; 4 blue, 6 green, 4 red; 3 blue, 2 green, 6 red; 4 green, 4 red, 1 blue; 5 blue, 12 red, 9 green +Game 9: 2 green, 20 blue, 4 red; 3 green, 7 red, 2 blue; 3 green, 17 blue; 20 blue, 7 red, 2 green; 4 green, 6 red, 1 blue; 7 red, 5 green, 19 blue +Game 10: 2 red, 9 green, 8 blue; 16 green, 1 red, 7 blue; 3 blue, 5 red, 9 green; 5 blue, 2 red, 11 green +Game 11: 6 blue, 3 green, 8 red; 6 blue, 4 green; 1 red, 3 green, 4 blue +Game 12: 18 red, 16 blue, 9 green; 10 green, 6 blue; 12 blue, 5 green, 15 red; 16 blue, 4 red, 8 green +Game 13: 2 green; 1 blue, 4 green; 1 green, 3 blue, 6 red; 2 red, 2 blue; 3 red, 2 green; 8 red, 2 blue, 5 green +Game 14: 8 red, 3 blue, 3 green; 3 green; 4 red, 7 blue, 5 green; 10 blue, 15 red, 1 green; 4 green, 14 red, 7 blue +Game 15: 8 red, 9 blue; 1 green, 4 red, 3 blue; 15 red, 3 blue, 1 green; 17 red, 6 blue +Game 16: 1 green, 10 blue, 13 red; 16 red, 1 green; 7 red; 9 blue, 12 red, 1 green; 6 red, 13 blue, 1 green +Game 17: 6 green, 1 blue, 1 red; 2 blue, 9 green, 1 red; 6 green, 1 blue, 2 red +Game 18: 5 red, 4 green, 1 blue; 5 blue, 6 red, 6 green; 12 red, 16 blue, 11 green +Game 19: 6 red, 9 green; 1 blue, 4 red; 12 green; 5 green, 2 blue, 9 red +Game 20: 15 blue, 15 red, 1 green; 2 green, 5 red, 13 blue; 15 red, 2 green, 15 blue; 3 green, 3 red, 13 blue; 6 blue, 1 green, 8 red +Game 21: 3 red, 3 blue; 4 blue, 3 red; 4 red, 8 blue, 1 green; 1 blue, 2 red, 7 green; 3 green, 3 blue; 3 blue +Game 22: 5 green, 3 blue, 7 red; 7 green, 1 blue, 5 red; 5 red, 3 blue, 3 green; 12 green, 7 red, 1 blue; 2 red, 3 blue; 7 green, 11 red, 1 blue +Game 23: 9 blue, 8 red; 9 blue, 9 green, 8 red; 3 red, 6 blue, 14 green; 3 blue, 4 red; 5 red, 14 green, 9 blue; 12 blue, 8 red, 8 green +Game 24: 15 green, 1 red, 1 blue; 6 red, 2 green, 7 blue; 7 blue, 2 green, 4 red; 8 blue, 5 red, 8 green; 5 blue, 3 red, 7 green; 6 blue, 12 green +Game 25: 7 blue, 16 green, 1 red; 13 green; 4 red, 9 green, 2 blue; 11 green, 1 red, 1 blue; 3 blue, 5 green, 5 red +Game 26: 2 blue, 11 red, 10 green; 5 green, 1 blue, 2 red; 7 green, 5 red, 14 blue; 11 green, 1 blue, 10 red +Game 27: 2 green, 8 blue, 2 red; 1 blue, 1 red, 5 green; 3 green, 7 blue +Game 28: 9 green, 15 red, 1 blue; 3 blue, 3 green; 18 green, 15 red, 7 blue; 3 red, 10 blue, 7 green; 6 red, 5 green, 8 blue; 2 blue, 7 red, 3 green +Game 29: 5 blue, 3 red, 7 green; 17 blue, 8 red, 11 green; 6 red, 5 blue, 12 green; 3 red, 10 blue, 10 green; 4 blue, 10 green; 6 red, 2 blue, 9 green +Game 30: 4 green, 5 blue, 1 red; 19 red, 18 blue, 3 green; 18 red, 18 blue, 1 green; 5 green, 14 blue, 4 red; 4 red, 3 green, 18 blue; 6 blue, 3 green, 17 red +Game 31: 2 red, 2 green; 13 red, 9 blue; 4 blue, 3 green, 1 red; 12 blue, 12 red, 4 green; 9 red, 6 blue; 12 red, 1 green, 2 blue +Game 32: 11 red, 5 blue, 9 green; 3 blue, 8 red, 15 green; 3 green, 7 blue, 17 red; 2 green, 9 red, 1 blue; 2 blue, 6 green, 2 red +Game 33: 13 blue, 2 green; 1 green, 1 red, 14 blue; 3 green, 6 blue, 1 red; 12 blue, 1 green; 9 blue, 2 green; 4 blue, 1 red +Game 34: 15 green, 2 red, 13 blue; 1 green, 6 blue; 2 red, 1 green, 7 blue +Game 35: 1 green, 12 red, 2 blue; 3 red, 5 blue; 6 red; 3 red, 3 blue; 4 red +Game 36: 6 blue, 8 red, 1 green; 7 green, 6 blue, 10 red; 7 blue, 9 green, 5 red; 7 green, 1 red, 1 blue +Game 37: 6 blue, 2 green, 4 red; 2 green, 3 blue, 6 red; 1 green, 17 red, 14 blue; 10 red, 2 blue; 19 red, 1 green, 8 blue; 2 red, 2 green +Game 38: 6 red, 1 green, 5 blue; 2 blue, 15 green, 6 red; 10 green, 3 blue, 6 red; 5 blue, 8 green, 2 red +Game 39: 8 blue, 5 green, 5 red; 4 green, 5 blue; 2 red, 7 blue; 3 green, 15 blue, 4 red +Game 40: 8 green, 12 red, 10 blue; 8 blue, 8 red, 9 green; 1 green, 10 blue, 9 red; 17 red, 7 green, 2 blue; 6 green, 11 red; 2 green, 2 blue, 8 red +Game 41: 11 red, 5 green, 1 blue; 5 green; 3 green; 2 red +Game 42: 8 blue, 11 red, 1 green; 12 red, 10 green, 6 blue; 2 red, 6 blue, 16 green; 18 blue, 2 red, 4 green; 10 blue, 10 green, 3 red +Game 43: 4 red, 3 blue; 2 blue, 10 red, 4 green; 3 blue, 7 red, 5 green; 2 green, 8 red; 1 green, 3 blue; 10 red, 1 green +Game 44: 1 red, 9 blue; 2 red, 19 blue; 2 green, 6 red, 15 blue; 11 blue, 8 red, 4 green +Game 45: 7 green, 4 blue, 1 red; 5 blue, 8 green; 5 blue, 8 green; 5 blue, 6 green; 6 green, 3 blue +Game 46: 2 red, 2 green; 6 red, 5 blue, 2 green; 13 green, 8 blue, 2 red +Game 47: 1 red, 5 green; 1 blue, 15 red, 5 green; 6 red, 6 green, 3 blue; 5 blue, 4 red; 4 blue, 7 red +Game 48: 16 blue, 16 red; 11 blue, 16 red; 15 red, 1 green; 6 blue, 1 green, 2 red +Game 49: 9 green, 20 blue, 7 red; 16 blue, 6 red; 9 green, 1 blue, 1 red; 8 red, 12 green, 15 blue; 3 blue, 2 green, 8 red +Game 50: 9 red, 6 green, 9 blue; 6 blue, 2 red, 6 green; 7 green, 4 red, 6 blue; 2 red, 7 blue, 9 green; 4 red, 8 green, 9 blue +Game 51: 1 blue, 2 red, 6 green; 1 blue, 4 red; 6 red, 2 green; 6 red, 8 green, 2 blue; 2 blue, 8 green, 4 red +Game 52: 10 green, 1 blue; 5 blue, 5 green; 5 blue, 2 red, 4 green; 2 blue, 12 green +Game 53: 3 blue, 8 red, 7 green; 7 blue, 7 red, 12 green; 8 blue, 9 green, 7 red; 7 red, 10 blue, 1 green +Game 54: 3 green, 4 blue; 1 blue, 5 red, 4 green; 7 red, 4 blue; 2 green, 4 blue; 1 red, 4 blue; 1 blue, 6 red, 5 green +Game 55: 7 red, 13 blue; 7 blue, 1 red, 1 green; 3 red, 5 blue +Game 56: 6 red, 3 green, 1 blue; 7 blue, 2 green, 5 red; 4 green, 4 red; 8 blue, 1 green; 6 green, 6 blue, 4 red +Game 57: 14 blue, 12 green, 8 red; 1 red, 20 blue, 10 green; 4 red, 16 green, 15 blue +Game 58: 3 blue, 12 red; 9 red, 3 blue, 2 green; 2 blue, 2 red; 7 red, 4 green, 5 blue; 10 red, 1 blue +Game 59: 7 red, 11 blue, 17 green; 5 red, 4 green, 7 blue; 8 red, 6 blue, 17 green; 16 green, 7 red, 6 blue; 5 blue, 12 green, 9 red; 7 blue, 3 red, 9 green +Game 60: 4 red, 5 green, 4 blue; 15 green, 4 red, 18 blue; 6 blue, 1 red, 1 green; 14 blue, 12 green, 1 red; 2 green, 5 red, 4 blue; 2 green, 1 blue, 5 red +Game 61: 3 green, 2 blue; 4 green, 6 blue; 2 red, 12 green, 11 blue; 1 red, 9 green, 7 blue; 2 red, 11 green, 19 blue; 9 blue, 1 red, 2 green +Game 62: 17 green; 3 blue, 14 red, 14 green; 17 red, 16 green, 5 blue; 17 green, 5 blue, 1 red; 4 blue, 17 red, 13 green +Game 63: 4 green, 2 red, 2 blue; 10 green, 15 blue, 3 red; 5 green, 5 blue, 5 red +Game 64: 9 red, 10 blue, 2 green; 1 green, 4 red, 1 blue; 5 green, 2 blue, 11 red +Game 65: 1 blue, 10 red, 5 green; 1 blue, 4 green, 2 red; 3 blue, 1 green; 11 red, 2 blue, 5 green; 9 green, 11 red, 3 blue +Game 66: 6 blue, 13 green, 2 red; 5 green, 1 red, 7 blue; 11 green, 3 red; 5 blue, 1 red, 2 green +Game 67: 1 red, 10 green, 4 blue; 5 blue, 3 red, 9 green; 4 blue, 3 red, 1 green; 14 red, 4 blue, 10 green +Game 68: 12 green, 3 red, 3 blue; 2 green, 1 red, 2 blue; 1 blue, 3 green, 3 red; 1 green, 1 red, 6 blue +Game 69: 3 blue, 10 red, 4 green; 4 green, 1 blue, 6 red; 1 blue, 1 red, 6 green; 4 red, 3 blue, 5 green +Game 70: 9 blue, 3 green; 1 red, 2 green, 6 blue; 9 blue, 2 green; 6 blue, 1 red; 6 green, 1 red, 6 blue; 3 blue, 1 red, 2 green +Game 71: 2 blue; 2 red, 3 blue; 12 blue, 3 red, 1 green; 1 green; 1 red, 7 blue; 1 red, 9 blue +Game 72: 1 red, 1 green, 5 blue; 19 blue, 1 red, 3 green; 3 green, 1 red; 1 red, 13 blue, 1 green; 1 red, 1 green, 19 blue; 6 blue +Game 73: 12 blue, 5 red, 5 green; 12 blue, 1 red, 4 green; 7 green, 4 red, 6 blue; 1 green, 4 blue, 10 red; 9 blue, 14 green +Game 74: 9 blue, 1 green, 2 red; 7 blue, 15 red; 5 red, 2 green, 17 blue +Game 75: 8 red; 1 green, 14 red; 2 blue, 3 green, 10 red; 2 blue, 4 green +Game 76: 2 red, 3 blue; 6 blue, 8 red; 6 blue, 9 red; 7 blue; 7 red, 1 green, 5 blue +Game 77: 6 green, 5 red, 12 blue; 16 blue, 5 red, 11 green; 4 blue, 5 green; 10 blue, 4 red, 9 green +Game 78: 7 blue, 2 red; 1 green, 5 red; 4 blue +Game 79: 3 green, 4 blue; 4 blue, 1 green, 2 red; 8 blue, 3 green +Game 80: 10 red, 8 green; 4 red, 1 blue; 7 red, 4 green, 4 blue; 6 green, 1 red, 3 blue; 9 red, 3 blue; 4 green, 8 blue, 13 red +Game 81: 3 red, 6 green, 9 blue; 9 red, 1 blue, 3 green; 5 red, 11 green, 1 blue +Game 82: 6 green, 11 blue, 8 red; 16 green, 9 red, 7 blue; 6 blue, 17 green, 4 red +Game 83: 6 blue, 1 green, 8 red; 3 green, 5 blue; 4 red, 2 green, 8 blue +Game 84: 2 green, 1 red, 5 blue; 1 red, 2 green, 5 blue; 2 blue; 9 blue +Game 85: 9 blue, 2 red; 7 green, 13 blue, 3 red; 11 green, 17 blue +Game 86: 2 green, 15 red; 12 red, 1 blue, 3 green; 2 blue, 4 red, 3 green; 5 red; 6 green, 2 blue +Game 87: 17 blue, 3 red; 3 red, 4 green, 10 blue; 3 red, 14 blue, 4 green +Game 88: 13 green, 10 blue, 10 red; 14 green, 3 red, 4 blue; 13 blue, 7 red, 16 green; 10 blue, 6 green, 1 red; 9 red, 4 green, 14 blue +Game 89: 3 green, 16 blue, 14 red; 4 green, 13 red, 1 blue; 6 red, 17 blue, 1 green; 4 red, 7 blue +Game 90: 2 blue, 2 red; 5 blue, 10 red, 6 green; 10 red, 3 green, 1 blue; 10 blue, 6 green, 7 red +Game 91: 15 green, 5 blue, 12 red; 9 red, 1 green, 4 blue; 2 red, 15 green, 3 blue; 18 green, 5 blue, 2 red +Game 92: 7 green, 7 blue, 12 red; 7 blue, 9 red, 2 green; 11 blue, 10 red, 10 green; 2 green, 4 red, 11 blue; 12 red, 4 blue; 2 red, 6 green +Game 93: 2 green, 8 blue; 2 blue, 1 red, 3 green; 4 blue, 8 green, 1 red; 8 blue, 5 green; 3 green +Game 94: 16 red, 1 green, 5 blue; 11 red, 9 blue; 5 red, 2 green, 6 blue +Game 95: 4 blue, 7 red; 7 red, 10 green; 11 green; 2 red, 10 green; 6 blue, 8 red; 8 red, 2 green, 6 blue +Game 96: 9 blue, 12 green; 6 green, 9 blue, 11 red; 7 blue, 5 green, 10 red +Game 97: 1 green, 6 red, 1 blue; 6 red, 3 green, 6 blue; 9 green, 5 blue, 9 red; 13 red, 7 green +Game 98: 9 red, 12 green, 2 blue; 1 blue, 11 green, 10 red; 10 red, 2 green +Game 99: 4 red, 13 blue, 7 green; 7 green, 5 blue, 6 red; 7 green, 11 blue; 10 green, 2 red, 8 blue +Game 100: 2 green, 1 blue; 9 red, 8 green, 1 blue; 4 red, 10 green, 1 blue; 17 green, 8 red; 5 green, 1 blue, 7 red; 14 red, 12 green diff --git a/src/day2.rs b/src/day2.rs new file mode 100644 index 0000000..84397ed --- /dev/null +++ b/src/day2.rs @@ -0,0 +1,99 @@ +#[derive(Debug, Clone)] +struct Draw { + red: u32, + green: u32, + blue: u32, +} + +#[derive(Debug)] +struct Game { + id: u32, + draws: Vec, +} + +impl std::str::FromStr for Game { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let parts = s.trim().split_once(':'); + if parts.is_none() { + return Err("Cannot find separator in input") + } + let id_part = parts.unwrap().0.split_once(' '); + if id_part.is_none() { + return Err("Cannot find separator in id part") + } else if id_part.unwrap().0 != "Game" { + return Err("Not a game?") + } + let id = id_part.unwrap().1.parse::().unwrap(); + + // Rest is `;` separated instances, and in there `,` separated `NUM COLOR` pairs. + let mut draws = vec![]; + for s in parts.unwrap().1.split(';') { + let mut draw = Draw { red: 0, green: 0, blue: 0 }; + for color_draw in s.split(',') { + match color_draw.trim_start().split_once(' ') { + Some((count, "red")) => draw.red = count.parse::().unwrap(), + Some((count, "green")) => draw.green = count.parse::().unwrap(), + Some((count, "blue")) => draw.blue = count.parse::().unwrap(), + _ => { + return Err("Not a known color") + } + } + } + + draws.push(draw) + } + + Ok(Game { id, draws }) + } +} + +impl Game { + pub fn is_possible(&self, red: u32, green: u32, blue: u32) -> bool { + for draw in self.draws.iter() { + if draw.red > red || draw.green > green || draw.blue > blue { + return false + } + } + true + } +} + +fn sum_of_possible_games(input: &str) -> u32 { + let mut result = 0; + for line in input.lines() { + match line.parse::() { + Ok(game) => { + if game.is_possible(12, 13, 14) { + result += game.id; + } + }, + Err(reason) => println!("error = {}", reason) + } + } + result +} + +pub fn main() { + match std::fs::read_to_string("day2.input") { + Ok(input) => println!("value = {}", sum_of_possible_games(&input)), + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sum_of_possible_games_example1() { + static DATA: &str = "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"; + + assert_eq!(sum_of_possible_games(DATA), 8); + } +} diff --git a/src/main.rs b/src/main.rs index e2dd68b..73fd7c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day1; +mod day2; fn main() { - day1::main() + day2::main() } From 8a4e9757c6cea61f38a96f8461b284c1aa7480c6 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 2 Dec 2023 22:19:45 +0100 Subject: [PATCH 064/120] Day 2, part 2: min max. --- src/day2.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/day2.rs b/src/day2.rs index 84397ed..75c2dd8 100644 --- a/src/day2.rs +++ b/src/day2.rs @@ -75,9 +75,37 @@ fn sum_of_possible_games(input: &str) -> u32 { result } +fn sum_of_minimal_powers(input: &str) -> u32 { + let mut result = 0; + for line in input.lines() { + match line.parse::() { + Ok(game) => { + let mut max_red = 0; + let mut max_green = 0; + let mut max_blue = 0; + + for draw in game.draws { + if draw.red > 0 { + max_red = std::cmp::max(max_red, draw.red); + } + if draw.green > 0 { + max_green = std::cmp::max(max_green, draw.green); + } + if draw.blue > 0 { + max_blue = std::cmp::max(max_blue, draw.blue) + } + } + result += max_red * max_green * max_blue; + }, + Err(reason) => println!("error = {}", reason) + } + } + result +} + pub fn main() { match std::fs::read_to_string("day2.input") { - Ok(input) => println!("value = {}", sum_of_possible_games(&input)), + Ok(input) => println!("part1 = {}, part2 = {}", sum_of_possible_games(&input), sum_of_minimal_powers(&input)), Err(reason) => println!("error = {}", reason) } } @@ -96,4 +124,15 @@ Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"; assert_eq!(sum_of_possible_games(DATA), 8); } + + #[test] + fn sum_of_minimal_powers_example2() { + static DATA: &str = "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"; + + assert_eq!(sum_of_minimal_powers(DATA), 2286); + } } From 4915630daf02b478a71f9476b7d34658ba275393 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Sun, 3 Dec 2023 16:11:31 +0100 Subject: [PATCH 065/120] Silence the cmake extension For some reason the extension thinks this is (or could be?) a cmake project, and wants to "Configure" it. --- .vscode/settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6537445..8e9f09b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,4 +2,5 @@ "editor.formatOnSave": true, "editor.formatOnSaveMode": "modificationsIfAvailable", "rust-analyzer.check.command": "clippy", + "cmake.configureOnOpen": false, } From 896a0f7949c24054de8d87e85c41fbfb652b1fb1 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Sun, 3 Dec 2023 16:12:15 +0100 Subject: [PATCH 066/120] Day 3, part 1: More parsing, but now in 2D Copilot did a pretty good job here initially, but it also shows that you cannot replace the humans yet: Copilot absolutely doesn't understand what we are trying to build, and based on the function names it can only guess so much. --- day3.input | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/day3.rs | 131 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 +- 3 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 day3.input create mode 100644 src/day3.rs diff --git a/day3.input b/day3.input new file mode 100644 index 0000000..b745e3a --- /dev/null +++ b/day3.input @@ -0,0 +1,140 @@ +.......497...........................858...923...128..................227..801........487.....664........................................... +436........765..............140.......+....................859.............*.........+.................960........668....................... +...*982...........=..........=....203......266.263...375*....=...402....691..-....................*..........575....................13...... +.............114...588...............*............*......631........*.......952...463..14.......661..........=...706......*333.........595.. +...194.........*..............743...917.&......375.....................................*...............544*.......*....664.................. +...*.....807..452....81..........*......969..#......309*................/....873....941...828.197..........427.728...............566...13... +.243........*.....80.......329....470.......145.475.....111........*659..259....+........*....%........569..............%.....*....*....*... +.........130......*....385*............123......................199.......................640.....463..%.........978....920...266..380.83... +.....323........870.........+...........$.........466......453........................297...........*............*.......................... +........*.=..............588.....*786......$.........*........*.......390*.....886...*....227...728..852.......606....*863.......916..396... +.....538...287................301........133.....539..........33.537......466..$...793..+..........*...............218.....721........*..... +...............986.........=.......................................*...%...............222..-.......701.271...............#.........437..... +......*3.........*.626.68...419...740...........................806...976.......875.........174..............735.............=488........... +...790.........487....*................./532..13............................*....-.....503..........*11..734..........978.19......622....... +...................&....712.68=.619+.........*.......................863...596.....2.....*.......160.....+...&659........*.........-....-757 +437*.......#........520...*..........304....568.974.255.318.183.........*.......&.....675......................................849.......... +....161.....687.710.....854.............*.......*......*....&...441......891.....476..........616.......$........235..434.880...*..673+..... +..................*...............683.....800.120..............*....807..................................707.....*....-....*...74........562 +....@...#988...487..#685..........-......*..............251.146.............................142@....74...........398....769..........238*... +....848....../................-.$.....662.........773..*...........895.......591...........................233.............................. +797.........611..........@.186...429..........304*....468.....554....*..........*...960......82.......*810...+.534..660....645...313./...... +......239..............509...............720*......................844..939=..508......*...........401............*.......*.......*...649... +........=........158.......$.....=...........200......409....982.....................46................126.....517....303.647.660........... +...530....=......*..........704.69...................*.......*..................@879........589..131.................*........*............. +......*..871...672....................611*........415.......283.569.21....842/........-109.&.......*.......157$...719.......679.$........... +....664..............664......668.........203....................&...%............................14..................427.......833..484.... +....................*........*.......434.......796...........65............................................-479.126..*..............+....... +.....382..........121.....836.........*........@...............*789.......624........350&..........*544............$.6.........882....513... +....%.....406.........................848........625...%...88.........382..+..971.................5......*622...........914....*....%....... +..............627....816........641..............*.....373./.............*..../...912..651.162........557........901...&.....503.337....59.. +...357...........*.........552...*..816..........240......................636.....*...*.....*.............@..993....*....................... +......*934....961...=..43..*...324.....@...............726.888....370...........170.805...517........639.389....*..929.................953.. +.16...............408.*...94..................................*......&..............................*......../...9........605............... +.......571....13......512........591+.......976.......895....489...........751.......474.760.........240.....931............*............... +...464../..................608..............*........*................$.94*........................................486.......172............ +...*......121........=.....*.......$......909.......583............128........929...................765.............*............+....24.... +.............*.......762....230..422..285.....434......................390.....=.....921.................261....#...949.....382...903.*..... +............595........................*.......*...................833*..............%.......973..$....@...*.268........506*..........251... +967...................................25....234...........................306....281..........=..36..918.432....../406........344...$....... +.....700*610.......=...839......917......33......610@................537....=....@............................%........20.402.@.....926..... +..............%.768...*....................*...@............93..161.%...............74$......%.........96..298..........%..+............+519 +...........925.......586...................264..85...721....*...*.............................371.................822.=..................... +...............540...........-....447....................987.....305.............379@.707..............670...397...*..842....552.464........ +.....666......*....844....515.......*..............+114..............977...............&...393........*.........$.800...........*........... +.....*...647...696..*..............203....................418.....19............522........*.......462................57...786..........561. +....691.....$.......756...165.....................596.32...%........#..280.259$..........398..............425.............*....719..796..... +.............../.........=........1/..305............*.........451......&..........332.......706............&.......327.841...........*..... +.74..........791.............=........+.....................+...-..................+..........*.....................*...............419..371 +...*927..........352.......148..........401....459...+....998......$783........@............444..$.......959..106.366....................... +............190..........*......385.............*....846......................907.826..585.......447.441..*..*............7......871........ +.................142....944....$.................634.............587..@..930..........*......935.....*...819.29.....3......*35.............. +......967....415*......................=980.....................%....58.-......317..74......../.....922..............-.207........../....... +.........................................................................................................175....................369.233..... +.........................+....645.$........%.....620.+429....951......616.................................*............524$................. +....799...551*602........920..+....503..654....-...*............*....=......395.........451....263.......897..................370........... +......-.......................................409......970....661.............*............+...*....48...................475..$........839.. +..97...................../.....@497....%..........446$...*...............533..794.....432-.....167...*.....722...486........*...500...*..... +..............459......540.............110................569............&..................#.....................#........785.*.......455.. +........815....*...........................*452......./......................365.........929....*978.=................709........+..84...... +....427*......466.............608*796..............680......................*......&.........142.....603.................#......621..*...... +.........635............@....................302..................296-.....679...801..290..................464..............980......627.... +....../.../........%...850.......*108....513*........656...*739........715...............@.......713.......*...................*............ +354+..245.......629...........995.....................$..41.....=.....@.....................45..........840......506+...$.....148........... +..........995.................................&541............914.510.....950...../...........*53..28...................275........138...... +.............*812..665...../.........................101.308..............*......691.482.............*........902.585.......@.......*....... +.........../........./...292...............#..........-....*....@307......661..........*.210......135....932%...........992..54..191..931... +...400..649...............................504.196.........88........................581.............................743*.............&...... +...*.........140..............642....891.............309...............................................695......361..............603........ +....170.643#..*.................*....*.......*24.....*....................932.291.....538....461.........*........*..275............&....... +.............725......494......23...279...713..../....449............*........*...../...=......*..........434..............785.............. +.....991..........946.............................830.........136.439.24...519......289.......408...579........708.650*......*.370.13....410 +......*..887........#..688.673.........218......................-...............941....................$.......%.......927.722....*......... +....124....*...........*..../....427....*.............312................................................922...........................307.. +...........706...16..934..*.......*......608....459..&..........761.....................647..641...........*.............242............*... +..5*715..-........+........122.....262........./...........928....%............728..610*......*..502.....222..40.....923..+...........540... +.........701.............=..............291...............*.........351.........*............141.%............*.../.....*....725............ +..............314.......878....%.......*......=..820*.....988..204.....-.....889......119............797...........395....+.............287. +..................671........322....101......257.....733........@.....................=.............*..........544......600.......862....... +..421.......582...%..............................484...............565.....+...831...........695...384.#...592.=............240....../.904.. +....*..........*........570...........&....=........*629......717&.*.......93......726../961....*......535..*........767../......715....*... +....439.....630............../..%...615...912......................777............*..............602.........567..3........107....$..77..... +....................914.....3...2.=.............763...&885......................185....182.......................*......-......+............ +...372...383........*..............60.............*............&..38.681...............*.....459....../........117...504......358..480-..... +............+.990..33...........................834.......@..33......................494....*........181.66+................................ +...............*......*...492..............176..........857...........376.315................954.....................*982.......763......... +329=..........179....245...*...61...........*...*................%......+....*.....352*509.........952#..69..620..423.............*......... +.........................131.....*17......191.33.306...../.....144..503......491.............................................298...415...... +...................$...................................426.........*...............526.669.....&498..698...$............447.....+........... +.............575...142.617......890..............%...............212..730.519.971..&......*384.........@....18.219.........*................ +.......*537..*.........*........*.........677...587..407...120*........./....*...................................+......334..........700.... +....944......636..848........743.....388..*....................109..........................................................540.40..*....... +.................*....596............*....155..324...820.520.................=...............443...94...........621.276......*..+..910...... +...............276.....-.........376...........*........*....................739......368....=..............428....*......434..........878.. +932....28.....................-..=....207......959....................289.........196.*........................*...............-.......=.... +...*........................172....#.#.....688.........25..944...725...&............*..110.....148...426.483..771../932......800............ +.947............................457....931*.............-....*...#.......834......721.........*.........*.............................477... +.....*491......*.........*114.................191.....$...213........909*...................194............633....%...792..605.633...#...... +.............108......611.....+719...........*.....696........865...............120................=724...%....950.../......*...../......... +...320............*.................260/...121.........338...*........719.180.........516.....*.............................649............. +.....#...643.......941......*160......................*......140...94....*...............*..39.789................*......&.........81...597. +............*..135.......532.................%90...608............*............+515....743.............+...194.993.669..259..+.............. +.....%....948.....*............262..695.712....................623.....*...................473........602...*...............83......679..... +..259.............447.............%.*...............363.............105...................@........=......+.........................*....... +......957....659........299..........................%...599..898.+.................464.......606.237..768..416@....=...............228..... +.376..$.........*..........*..2.........@557......./.......*.*.....517..........859*.........*....................855...877.427.........*... +.........*468..535......500....$................117......726.381........428...$................@........43....472.......*...*...........476. +......517................................951........%............-..249..@.....920...........859........*........*....825.393...15.......... +...........770.......&16.....278...417......$.....626...-23....954.....#..............................868.......502............*............ +.....373..*...................%...*.....254................................................246.#530....................982....179....635.... +......*...538.....................362...-...........162.........................180=........*..................278.......*............+..... +....138.......922..............................543................6....12....&.............92...150...............*.......994............... +................+.....+................388....*..........................*....788............../..................220.............834....... +.....................301.593.597.............500..603......928....966................/.............536.......768.............800............ +................*64........*.../..&.....924.........*........-...$....................203.............-...+..../...............*..423.&451.. +.............453....*......638.....314..*...896....459...............96...................186............581................846....*........ +....&188.........624.400...............268....@...........................664...............*...12.943............#733...................... +.............................597...765................388......149..468.....+............698......*....143........................426....... +.......................878...*.........875..............*..871*.....*..............929....................$.504*..............473.%......... +...245..........94.651..*.....915.........*.........40.440........236.................*511.45........994........753..................887.... +...#..............*.....459............212...18*964.*.........=71..........768..827............./.....*......................567............ +.....787.2..781*....................................827....................*...*..............437.....813.......317.....102.....*333........ +..........*.....285............@..-...........304.......821.622.....953...377.997......320....................@./.....%....*..........254... +.......877..636.....42......772..419.....189..*................&....*.....................=.17......366*....563......228...153.............. +...............*.....$................&....*...839......218.........449......................*..409.....69............................652... +.....576......255..............593...397............469..%......#.......+568.......374......499....*...........541..477.........%137..*..... +.......*............@319.................$.35..........*.....207...............808*.................933.737...........*.502............367.. +.....807....219../.....................436......226@...266........215...................................*................................... +..............*...769.....41*....922............................$..*.......271.........350..........677.346......................662....725. +..............175............979.*...#........215..............652..39......$....=61......*..154...................................*........ +...426..............335*.........487.194.........*42...................790.............+.750.@......&..............253...337....617..717.... +...+....908.............489.................../............14...278.../....953.......316.......*856.44.50...../.......*................$.... +.........%..90.................437..........848...........................*......714........708..........*223.588.....884....871.801........ +494@..........*..33...........*.........779.....424.550....923............779.......*...340........738.......................*....*..131.603 +.....50..481.........=.....643...........@......%............*.......815......681..263....*........*...5.....256*11.377$....872.903.*....... +.....*...............635.......698..........583...148........708........................323.243..201.....................*..........377.132. +...502........883............/..*..............$...*....994.........*....479@.................$......804.443..........584................... +.............*..............893..581..534........376..+..........174.119.........138............670...*....$.834............4............... +.....+....234...904.323..=..............&.894..........439.@838............*.....*........47........555........*............*........932.... +...594............*...$.654.....+.........*........................84.*....7...231.$102.......286.......*760....817.......719.........*..... +..................620............806......866.................559......440...........................310...........................590..547. diff --git a/src/day3.rs b/src/day3.rs new file mode 100644 index 0000000..00b6c98 --- /dev/null +++ b/src/day3.rs @@ -0,0 +1,131 @@ +use std::str::from_utf8; + +struct Schematic { + width: usize, + lines: Vec>, +} + +impl std::str::FromStr for Schematic { + type Err = (); + + fn from_str(s: &str) -> Result { + let lines: Vec> = s.lines().map(|line| line.as_bytes().to_vec()).collect(); + let width = lines[0].len(); + for line in &lines { + if line.len() != width { + return Err(()); + } + } + Ok(Schematic { width, lines }) + } +} + +impl Schematic { + fn to_u32(s: &[u8]) -> u32 { + if let Ok(s) = from_utf8(s) { + println!("s = {}", s); + return s.parse::().unwrap(); + } + panic!("invalid input") + } + + fn has_symbol_around(&self, y: usize, x1: usize, l: usize) -> bool { + let mut has_symbol = false; + 'outer: for y in y.saturating_sub(1)..=y+1 { + if y >= self.lines.len() { + continue; + } + println!("has_symbol_around(y = {}, x1 = {}, l = {}): y = {}", y, x1, l, y); + let line = &self.lines[y]; + for c in line.iter().skip(x1.saturating_sub(1)).take(1 + l + 1) { + print!("{}", *c as char); + match c { + b'.' => continue, + b'0'..=b'9' => continue, + _ => { has_symbol = true; break 'outer; } + } + } + println!() + } + println!("has_symbol_around = {}", has_symbol); + has_symbol + } + + fn sum_of_part_numbers(&self) -> u32 { + let mut sum = 0; + for y in 0..self.lines.len() { + println!("y = {}", y); + let line = &self.lines[y]; + let mut x = 0; + while x < self.width { + match line[x] { + b'.' => { x += 1; continue }, + b'0'..=b'9' => { + // Part number + println!("found part number at ({}, {})", y, x); + }, + _ => { x += 1; continue }, + } + + let mut l = 0; + while x+l < self.width && line[x+l] >= b'0' && line[x+l] <= b'9' { + l += 1; + } + + // It's a part number, check whether it is connected to a symbol + // or not. + if self.has_symbol_around(y, x, l) { + sum += Schematic::to_u32(&line[x..x+l]); + } + x += l; + } + } + sum + } +} + +fn sum_of_part_numbers(input: &str) -> u32 { + if let Ok(schematic) = input.parse::() { + return schematic.sum_of_part_numbers(); + } + panic!("invalid input") +} + +pub fn main() { + match std::fs::read_to_string("day3.input") { + Ok(input) => println!("sum_of_part_numbers = {}", sum_of_part_numbers(&input)), + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn has_symbol_around_trivial_false() { + let schematic = Schematic { width: 3, lines: vec!["123".as_bytes().to_vec()] }; + assert!(!schematic.has_symbol_around(0, 0, 3)); + } + + #[test] + fn has_symbol_around_just_before() { + let schematic = Schematic { width: 4, lines: vec!["*123".as_bytes().to_vec()] }; + assert!(schematic.has_symbol_around(0, 1, 3)); + } + + #[test] + fn sum_of_part_numbers_example() { + static DATA: &str = "467..114.. +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.."; + assert_eq!(sum_of_part_numbers(DATA), 4361); + } +} diff --git a/src/main.rs b/src/main.rs index 73fd7c1..35459aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day2; +mod day3; fn main() { - day2::main() + day3::main() } From 8133e6a85fde6f82297feca7c2a104614d53d1a9 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Sun, 3 Dec 2023 20:18:22 +0100 Subject: [PATCH 067/120] Enable automatic trimming of trailing whitespace This happened automatically in go, but needs a bit more push for rust. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch main # Your branch is up to date with 'origin/main'. # # Changes to be committed: # modified: .editorconfig # # Changes not staged for commit: # modified: .vscode/launch.json # modified: src/day3.rs # --- .editorconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/.editorconfig b/.editorconfig index 7a952c1..f950f83 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,7 @@ root = true [*] end_of_line = lf insert_final_newline = true +trim_trailing_whitespace = true [*.go] end_of_line = lf From c9f66e0a0a41c509975b15a6b6f306ad2ce81e2b Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Sun, 3 Dec 2023 20:18:27 +0100 Subject: [PATCH 068/120] Day 3, part 2: Shuffle things around a bit In a real-world situation we would probably build up the structure once, and then reuse it; for AoC we can afford copy-paste-modifying things for the two different tasks. Interesting discussion here: Would one track the symbols or the parts? --- src/day3.rs | 138 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 117 insertions(+), 21 deletions(-) diff --git a/src/day3.rs b/src/day3.rs index 00b6c98..14b8060 100644 --- a/src/day3.rs +++ b/src/day3.rs @@ -5,6 +5,20 @@ struct Schematic { lines: Vec>, } +#[derive(Debug, PartialEq)] +struct Pos { + y: usize, + x: usize, +} + +#[derive(Debug, PartialEq)] +struct Symbol { + pos: Pos, + symbol: u8, +} + +type PartNumber = u32; + impl std::str::FromStr for Schematic { type Err = (); @@ -29,33 +43,35 @@ impl Schematic { panic!("invalid input") } - fn has_symbol_around(&self, y: usize, x1: usize, l: usize) -> bool { - let mut has_symbol = false; - 'outer: for y in y.saturating_sub(1)..=y+1 { + fn symbols_around(&self, y: usize, x1: usize, l: usize) -> Vec { + let mut symbols = vec![]; + for y in y.saturating_sub(1)..=y+1 { if y >= self.lines.len() { continue; } - println!("has_symbol_around(y = {}, x1 = {}, l = {}): y = {}", y, x1, l, y); let line = &self.lines[y]; - for c in line.iter().skip(x1.saturating_sub(1)).take(1 + l + 1) { + let skip = x1.saturating_sub(1); + for (x, c) in line.iter().enumerate().skip(skip).take(1 + l + 1) { print!("{}", *c as char); match c { b'.' => continue, b'0'..=b'9' => continue, - _ => { has_symbol = true; break 'outer; } + _ => { + symbols.push(Symbol { pos: Pos { y, x }, symbol: *c }); + } } } println!() } - println!("has_symbol_around = {}", has_symbol); - has_symbol + println!("symbols_around({},{},{}) = {:?}", y, x1, l, symbols); + symbols } fn sum_of_part_numbers(&self) -> u32 { let mut sum = 0; for y in 0..self.lines.len() { println!("y = {}", y); - let line = &self.lines[y]; + let line = &self.lines[y]; let mut x = 0; while x < self.width { match line[x] { @@ -74,7 +90,7 @@ impl Schematic { // It's a part number, check whether it is connected to a symbol // or not. - if self.has_symbol_around(y, x, l) { + if !self.symbols_around(y, x, l).is_empty() { sum += Schematic::to_u32(&line[x..x+l]); } x += l; @@ -82,18 +98,72 @@ impl Schematic { } sum } -} -fn sum_of_part_numbers(input: &str) -> u32 { - if let Ok(schematic) = input.parse::() { - return schematic.sum_of_part_numbers(); + fn sum_of_gear_ratios(&self) -> u32 { + // Gears that might be connected to parts + let mut gears: Vec<(Pos, Vec)> = vec![]; + + for y in 0..self.lines.len() { + println!("y = {}", y); + let line = &self.lines[y]; + let mut x = 0; + while x < self.width { + match line[x] { + b'.' => { x += 1; continue }, + b'0'..=b'9' => { + // Part number + println!("found part number at ({}, {})", y, x); + }, + _ => { x += 1; continue }, + } + + let mut l = 0; + while x+l < self.width && line[x+l] >= b'0' && line[x+l] <= b'9' { + l += 1; + } + + // It's a part number, check whether it is connected to a symbol + // or not. + for symbol in self.symbols_around(y, x, l) { + if symbol.symbol != b'*' { + continue + } + let part_number = Schematic::to_u32(&line[x..x+l]); + let open_gear = gears.iter_mut().find(|(gear, _)| gear.x == symbol.pos.x && gear.y == symbol.pos.y); + if let Some((_, parts)) = open_gear { + parts.push(part_number); + } else { + gears.push((symbol.pos, vec![part_number])); + } + } + x += l; + } + } + + println!("gears = {:?}", gears); + + // Calculate the sum of the gear ratios where each gear is connected to + // exactly two parts. + let mut sum = 0; + for (_, parts) in gears { + if parts.len() == 2 { + let ratio = parts[0] * parts[1]; + sum += ratio; + } + } + sum } - panic!("invalid input") + } pub fn main() { match std::fs::read_to_string("day3.input") { - Ok(input) => println!("sum_of_part_numbers = {}", sum_of_part_numbers(&input)), + Ok(input) => { + if let Ok(schematic) = input.parse::() { + println!("sum_of_part_numbers = {}", schematic.sum_of_part_numbers()); + println!("sum_of_gear_ratios = {}", schematic.sum_of_gear_ratios()); + } + }, Err(reason) => println!("error = {}", reason) } } @@ -103,15 +173,15 @@ mod tests { use super::*; #[test] - fn has_symbol_around_trivial_false() { + fn symbols_around_trivial_false() { let schematic = Schematic { width: 3, lines: vec!["123".as_bytes().to_vec()] }; - assert!(!schematic.has_symbol_around(0, 0, 3)); + assert_eq!(schematic.symbols_around(0, 0, 3), vec![]); } #[test] - fn has_symbol_around_just_before() { + fn symbols_around_just_before() { let schematic = Schematic { width: 4, lines: vec!["*123".as_bytes().to_vec()] }; - assert!(schematic.has_symbol_around(0, 1, 3)); + assert_eq!(schematic.symbols_around(0, 1, 3), vec![ Symbol { pos: Pos { y: 0 , x: 0 }, symbol: b'*' } ]); } #[test] @@ -126,6 +196,32 @@ mod tests { ......755. ...$.*.... .664.598.."; - assert_eq!(sum_of_part_numbers(DATA), 4361); + let schematic = DATA.parse::().unwrap(); + assert_eq!(schematic.sum_of_part_numbers(), 4361); + } + + #[test] + fn sum_of_gear_ratios_reduced_example() { + static DATA: &str = "467..114.. +...*...... +..35..633."; + let schematic = DATA.parse::().unwrap(); + assert_eq!(schematic.sum_of_gear_ratios(), 467 * 35); + } + + #[test] + fn sum_of_gear_ratios_example() { + static DATA: &str = "467..114.. +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.."; + let schematic = DATA.parse::().unwrap(); + assert_eq!(schematic.sum_of_gear_ratios(), 467835); } } From 8640c9c0a642626c1bea615625ecec80a4f72714 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Sun, 3 Dec 2023 21:20:21 +0100 Subject: [PATCH 069/120] Remove the embedded whitespace in the test data --- src/day1.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/day1.rs b/src/day1.rs index 768a2bc..501618c 100644 --- a/src/day1.rs +++ b/src/day1.rs @@ -117,9 +117,9 @@ mod tests { #[test] fn calculate_calibration_value_example1() { static DATA: &str = "1abc2 - pqr3stu8vwx - a1b2c3d4e5f - treb7uchet"; +pqr3stu8vwx +a1b2c3d4e5f +treb7uchet"; let value = calculate_calibration_value(DATA); assert_eq!(142, value); } @@ -127,12 +127,12 @@ mod tests { #[test] fn calculate_calibration_value_example2() { static DATA: &str = "two1nine - eightwothree - abcone2threexyz - xtwone3four - 4nineeightseven2 - zoneight234 - 7pqrstsixteen"; +eightwothree +abcone2threexyz +xtwone3four +4nineeightseven2 +zoneight234 +7pqrstsixteen"; let value = calculate_calibration_value(DATA); assert_eq!(281, value); } From d9e25370ced9b9b9b7a97bbf7518a1b9a6f25eee Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 5 Dec 2023 20:52:05 +0100 Subject: [PATCH 070/120] Day 4, part 1: Some counting Switched from parsing-via-split to parsing-via-token-and-state-machine ... we're definitely getting more complex. --- day4.input | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/day4.rs | 125 ++++++++++++++++++++++++++++++++++ src/main.rs | 4 +- 3 files changed, 315 insertions(+), 2 deletions(-) create mode 100644 day4.input create mode 100644 src/day4.rs diff --git a/day4.input b/day4.input new file mode 100644 index 0000000..7d75f06 --- /dev/null +++ b/day4.input @@ -0,0 +1,188 @@ +Card 1: 95 57 30 62 11 5 9 3 72 87 | 94 72 74 98 23 57 62 14 30 3 73 49 80 96 20 60 17 35 11 63 87 9 6 5 95 +Card 2: 65 16 99 4 48 52 84 7 26 12 | 86 7 71 12 52 4 84 15 48 20 16 3 10 87 56 99 26 66 88 65 98 32 14 51 59 +Card 3: 19 70 1 34 10 79 23 58 64 68 | 95 14 64 53 19 63 83 46 77 75 3 12 70 65 22 13 66 34 23 89 94 50 69 79 68 +Card 4: 27 57 62 6 53 68 97 35 23 8 | 23 2 81 62 19 8 65 27 93 53 57 67 6 91 68 97 16 30 12 96 15 35 25 55 43 +Card 5: 49 95 30 21 42 63 92 97 89 93 | 35 34 46 89 93 29 42 21 63 49 77 30 95 27 28 62 72 32 97 54 75 56 4 58 92 +Card 6: 7 39 29 54 34 40 63 64 32 23 | 88 4 54 73 32 18 36 31 19 35 61 94 28 40 23 41 96 59 14 48 77 29 39 21 33 +Card 7: 20 58 79 66 51 65 72 27 62 67 | 37 7 90 62 3 17 88 58 86 28 55 42 15 20 79 94 38 92 76 41 30 93 25 24 14 +Card 8: 3 83 96 15 95 72 63 87 74 78 | 16 74 6 49 15 87 46 3 64 90 82 85 2 78 32 9 97 96 70 95 63 72 54 83 38 +Card 9: 40 74 17 75 12 97 71 15 30 83 | 13 21 15 12 8 81 50 7 44 67 6 40 30 76 22 75 42 79 5 97 83 60 71 47 74 +Card 10: 47 96 36 45 84 14 65 7 69 38 | 36 38 85 14 87 95 7 24 69 29 68 65 26 94 84 78 83 45 98 9 2 20 93 96 47 +Card 11: 22 5 16 86 91 96 27 39 8 30 | 14 98 84 51 11 5 23 36 40 81 82 78 13 2 43 39 42 68 34 71 10 38 61 70 46 +Card 12: 57 95 65 48 50 46 69 61 58 70 | 64 69 52 84 93 65 61 37 25 22 31 6 46 83 50 48 75 58 59 98 95 70 19 51 57 +Card 13: 67 63 56 28 11 81 43 60 93 57 | 61 67 82 60 7 11 98 78 50 33 84 64 74 63 28 15 56 66 39 57 69 54 65 8 12 +Card 14: 30 97 48 84 86 1 59 83 8 44 | 70 94 38 62 71 79 47 99 68 93 67 15 33 57 60 72 50 31 88 20 82 40 18 63 29 +Card 15: 7 2 46 28 61 63 17 95 32 47 | 56 97 17 93 36 78 16 25 18 33 61 90 10 55 82 26 2 69 43 22 96 37 64 74 95 +Card 16: 45 90 36 48 81 64 68 58 4 66 | 31 36 34 41 46 56 2 74 50 57 93 86 22 60 43 24 12 17 73 79 15 63 82 97 32 +Card 17: 1 82 47 86 6 33 52 51 98 91 | 88 98 26 33 82 93 16 45 65 68 47 96 39 83 14 86 61 71 75 90 3 54 59 77 9 +Card 18: 43 73 13 32 98 11 15 12 97 99 | 83 15 60 62 95 36 98 16 51 79 20 24 73 46 5 67 12 32 11 84 89 23 93 59 74 +Card 19: 54 93 71 65 66 56 26 97 33 24 | 67 24 89 17 99 18 5 54 26 14 57 10 3 33 91 94 16 80 97 49 12 46 19 75 38 +Card 20: 65 10 75 93 72 62 29 69 59 66 | 58 55 56 87 66 88 7 34 36 62 4 35 67 90 33 52 99 17 32 68 80 79 40 48 31 +Card 21: 93 75 39 12 21 77 99 46 4 24 | 39 19 98 59 43 14 28 9 89 81 1 5 63 87 48 95 41 36 29 27 44 15 50 17 18 +Card 22: 78 39 74 11 41 24 9 33 68 45 | 41 66 29 79 15 90 62 60 95 69 57 55 81 33 20 89 76 65 56 77 61 18 88 75 19 +Card 23: 64 16 33 77 80 89 90 50 57 4 | 46 94 45 42 82 61 67 3 76 74 96 79 7 70 73 97 11 34 35 72 55 51 36 12 13 +Card 24: 40 13 83 79 42 70 26 33 7 12 | 95 17 5 74 68 28 46 21 96 43 73 47 18 86 54 88 82 61 85 51 11 9 56 20 75 +Card 25: 97 54 33 84 85 49 4 26 25 67 | 22 41 72 84 25 16 85 8 83 62 15 33 97 17 38 67 69 51 45 77 28 87 24 54 4 +Card 26: 54 22 60 99 15 96 80 3 5 64 | 96 65 54 38 60 87 8 15 80 10 3 32 22 56 43 5 44 14 78 18 97 64 25 63 99 +Card 27: 88 93 30 77 33 46 38 66 7 20 | 96 75 30 77 83 76 54 46 15 66 38 88 55 40 22 21 34 42 29 20 71 16 28 61 18 +Card 28: 48 85 39 25 47 80 98 33 68 66 | 50 82 40 60 84 46 29 51 25 47 11 22 58 64 36 2 63 92 80 15 72 27 37 98 10 +Card 29: 85 92 67 13 70 60 9 35 18 98 | 44 16 66 33 81 56 58 73 64 85 39 40 49 63 23 17 19 1 28 62 2 65 10 68 11 +Card 30: 15 64 30 28 6 97 69 38 17 79 | 92 50 33 24 85 6 38 44 91 28 35 58 90 97 39 79 64 80 84 22 15 66 2 45 17 +Card 31: 7 74 79 40 62 55 16 48 59 97 | 31 70 34 85 23 17 4 92 12 66 1 50 43 87 27 64 11 28 26 47 94 2 36 15 39 +Card 32: 97 95 38 61 7 22 36 94 47 4 | 21 37 44 88 77 33 11 12 91 27 80 67 25 83 17 45 89 61 98 40 59 76 96 71 1 +Card 33: 15 35 9 39 25 62 57 19 81 47 | 64 57 71 56 35 25 33 1 76 97 48 84 44 79 82 39 19 74 78 59 14 49 81 29 11 +Card 34: 97 3 81 82 28 40 35 67 38 85 | 36 76 21 89 38 34 43 10 85 9 99 83 68 94 47 19 17 91 41 26 20 30 63 25 69 +Card 35: 43 49 58 92 57 71 56 28 33 3 | 32 1 70 43 29 93 54 63 58 27 14 28 51 31 81 57 25 50 87 90 82 73 97 7 12 +Card 36: 18 85 61 97 29 25 66 28 11 62 | 44 26 46 65 83 59 30 66 68 47 90 93 15 84 9 7 72 1 95 87 3 20 23 81 86 +Card 37: 97 22 74 4 43 78 76 8 26 1 | 4 93 24 5 80 37 48 12 59 32 50 71 66 69 52 23 34 25 57 89 51 99 41 56 63 +Card 38: 20 57 93 41 87 71 76 29 33 66 | 63 56 49 11 64 2 62 68 82 8 67 81 41 4 78 17 85 97 69 35 19 47 30 95 65 +Card 39: 6 81 87 68 29 23 76 9 44 33 | 74 71 60 82 98 72 85 57 7 96 84 30 19 3 35 12 22 50 15 26 94 65 62 61 83 +Card 40: 96 61 74 3 10 54 58 86 97 87 | 16 37 57 5 72 93 74 45 88 67 97 54 69 2 71 58 46 96 87 44 10 20 86 28 3 +Card 41: 28 83 7 40 32 56 82 70 14 22 | 82 81 37 73 76 65 35 56 17 40 83 29 39 6 80 61 25 28 31 32 1 38 42 85 8 +Card 42: 16 47 55 93 99 1 7 72 12 40 | 78 2 26 88 9 98 40 47 61 77 23 1 66 27 55 5 72 67 50 12 85 83 90 71 25 +Card 43: 17 94 80 60 24 12 20 66 99 41 | 53 69 76 97 15 54 29 73 98 33 30 45 24 19 70 66 16 78 6 90 61 96 32 89 46 +Card 44: 16 20 87 88 90 27 69 81 79 70 | 52 70 85 7 13 87 34 26 60 82 15 88 69 79 58 62 75 44 42 49 48 11 97 16 27 +Card 45: 72 9 25 20 48 79 15 2 49 67 | 4 3 60 85 48 73 15 98 25 84 95 80 22 7 58 72 44 67 79 20 40 70 1 29 13 +Card 46: 86 95 61 42 30 43 1 72 19 53 | 65 88 13 2 3 30 51 7 5 19 74 25 56 50 10 32 43 85 78 61 99 12 75 42 80 +Card 47: 80 62 17 58 21 95 18 65 19 54 | 23 1 28 41 80 46 18 17 35 54 19 40 43 62 96 77 45 90 13 21 12 66 52 53 65 +Card 48: 52 43 23 72 73 82 9 19 60 83 | 35 29 60 57 22 46 78 39 86 27 92 90 19 71 28 44 41 40 52 79 6 50 15 82 21 +Card 49: 10 19 28 81 32 46 42 8 54 16 | 42 93 82 62 95 67 59 8 87 36 28 35 38 31 75 70 96 10 56 1 54 44 4 88 24 +Card 50: 12 66 62 83 81 13 2 38 85 57 | 73 95 59 70 54 93 71 35 25 75 82 46 14 21 76 32 8 81 68 42 79 44 34 41 55 +Card 51: 62 51 82 74 97 93 49 94 76 58 | 4 46 69 1 33 38 68 89 59 91 57 67 3 92 19 53 77 50 94 48 62 26 98 9 81 +Card 52: 52 51 23 12 82 32 96 89 47 55 | 12 4 60 90 17 35 52 64 94 43 27 14 9 25 6 66 41 68 38 56 37 19 55 85 69 +Card 53: 23 59 46 4 62 48 71 20 50 1 | 41 77 25 16 35 34 44 81 65 17 78 15 42 12 72 55 57 3 58 88 40 95 66 13 74 +Card 54: 43 96 23 40 48 38 10 21 8 20 | 98 88 67 99 97 56 54 1 29 57 37 69 63 32 89 35 41 85 11 49 74 36 28 65 91 +Card 55: 9 66 49 29 54 15 36 93 50 13 | 84 79 55 53 41 8 78 89 18 40 56 61 45 7 88 63 37 4 67 85 90 28 34 51 10 +Card 56: 51 99 43 34 16 30 8 36 71 88 | 99 36 8 16 71 28 43 29 61 94 92 48 77 58 51 34 88 67 47 30 54 14 66 70 68 +Card 57: 46 90 29 80 82 93 4 66 57 91 | 90 57 74 20 54 42 93 60 88 80 5 78 82 51 7 29 4 55 33 89 32 12 27 63 44 +Card 58: 46 16 53 11 58 63 65 93 99 36 | 22 29 59 91 79 40 95 68 67 99 88 87 13 73 54 8 49 20 16 94 9 43 47 4 98 +Card 59: 57 93 76 90 32 22 30 9 98 88 | 48 93 22 33 14 92 80 3 2 17 82 54 42 63 41 74 56 87 45 52 71 35 70 32 60 +Card 60: 26 74 89 84 81 10 79 99 75 11 | 86 81 64 26 54 35 66 99 84 53 89 79 13 75 24 98 60 19 94 74 5 11 49 10 23 +Card 61: 51 99 9 36 82 83 40 25 97 39 | 2 82 72 65 7 17 63 28 16 84 34 56 37 81 25 13 26 50 73 51 40 94 49 8 39 +Card 62: 98 72 92 16 2 68 65 61 20 78 | 89 60 42 83 20 7 64 36 77 95 63 37 39 4 74 75 25 67 9 58 49 2 87 10 68 +Card 63: 17 86 72 89 44 30 21 64 36 84 | 72 30 91 27 31 50 64 7 25 9 89 84 17 86 92 71 13 63 36 2 41 28 33 94 82 +Card 64: 9 71 80 49 16 90 92 17 39 45 | 53 9 30 93 7 12 98 87 45 16 67 71 90 18 17 31 42 36 39 48 47 85 19 97 95 +Card 65: 76 39 34 30 80 38 16 45 46 58 | 16 79 45 51 40 67 31 49 30 22 85 63 57 34 76 80 3 48 46 36 38 58 19 55 6 +Card 66: 97 57 52 42 67 92 28 6 7 73 | 55 79 71 61 94 86 83 35 72 78 4 58 10 51 73 89 68 92 42 24 69 57 91 7 43 +Card 67: 99 35 28 30 61 98 51 73 4 85 | 90 34 58 69 21 59 36 97 96 98 44 47 12 15 61 29 28 42 99 51 52 71 19 40 73 +Card 68: 72 30 78 60 61 91 14 73 76 47 | 46 41 40 6 94 56 16 45 60 20 33 24 43 1 88 67 62 68 2 84 29 12 4 96 74 +Card 69: 14 20 41 89 85 13 98 6 33 4 | 36 99 26 58 49 55 16 68 15 52 30 35 28 21 82 57 65 56 7 37 3 20 14 47 22 +Card 70: 93 18 99 57 25 81 95 4 58 37 | 24 66 67 61 34 55 85 37 78 30 75 79 3 32 83 33 10 52 69 98 20 45 2 68 44 +Card 71: 47 27 78 40 34 56 59 62 26 93 | 50 18 84 99 64 10 97 22 85 20 15 19 72 31 58 89 37 6 26 44 68 60 43 21 17 +Card 72: 28 18 7 3 11 94 85 44 90 40 | 59 2 49 16 27 42 72 33 50 5 92 37 88 55 95 11 62 7 52 23 41 74 98 35 30 +Card 73: 1 46 31 33 20 19 97 89 15 45 | 50 77 71 24 88 87 74 95 56 44 42 70 4 75 96 25 21 11 59 47 29 35 83 2 85 +Card 74: 88 55 81 82 51 18 48 12 72 19 | 41 78 28 96 83 5 33 60 3 73 53 85 22 4 50 61 98 23 32 68 34 80 49 75 36 +Card 75: 17 93 50 45 57 97 39 3 87 32 | 79 87 59 15 1 71 54 37 80 85 14 93 45 3 24 50 94 74 75 64 55 97 17 76 21 +Card 76: 37 19 35 66 32 28 43 68 13 86 | 68 45 91 37 33 69 35 24 1 14 58 25 52 3 50 70 62 64 94 32 49 13 28 43 21 +Card 77: 5 6 46 30 74 35 48 94 26 88 | 82 55 59 35 74 92 36 26 48 5 7 98 27 42 60 94 11 71 6 33 23 30 56 25 46 +Card 78: 27 81 2 26 70 83 28 75 15 82 | 47 25 73 15 36 86 93 90 46 37 1 28 75 89 49 83 2 79 81 27 9 44 82 70 61 +Card 79: 35 38 41 81 18 89 9 34 55 16 | 21 31 76 69 50 45 88 63 89 70 15 96 99 8 67 42 20 59 74 19 48 37 98 10 39 +Card 80: 97 65 69 37 10 86 57 41 15 31 | 17 58 2 50 45 27 33 73 96 12 29 86 60 74 89 81 51 95 37 41 75 98 38 93 20 +Card 81: 12 6 42 18 14 74 61 85 47 28 | 13 49 34 78 81 75 57 11 95 3 69 27 2 42 44 76 54 4 68 48 24 53 52 20 15 +Card 82: 40 27 39 47 34 78 31 79 91 12 | 63 6 76 5 50 8 86 96 99 57 82 87 7 37 95 56 28 26 77 67 45 17 51 66 30 +Card 83: 38 96 19 65 28 70 54 95 62 15 | 29 26 46 50 32 18 89 93 22 24 1 52 2 39 59 86 69 56 72 58 25 70 54 7 10 +Card 84: 76 89 49 56 46 1 83 64 73 40 | 19 60 49 99 18 28 54 73 32 38 97 87 2 79 8 61 12 93 35 20 52 51 58 3 21 +Card 85: 77 86 68 78 37 82 93 17 15 36 | 9 19 79 80 39 8 15 54 68 27 98 50 46 41 88 12 34 47 76 93 81 7 35 85 73 +Card 86: 68 22 45 20 26 79 88 44 46 90 | 84 19 67 86 49 18 21 65 23 6 57 90 75 28 51 83 4 56 26 98 38 5 3 80 63 +Card 87: 43 34 86 6 75 41 38 17 22 61 | 54 95 20 36 72 28 59 90 40 50 63 81 89 30 92 32 26 78 53 42 46 15 73 51 7 +Card 88: 15 32 22 2 63 17 62 94 99 83 | 44 25 22 16 58 54 67 4 92 8 75 27 41 99 53 97 76 5 51 32 78 74 73 81 45 +Card 89: 67 75 27 99 94 7 57 15 40 65 | 61 42 96 13 53 56 3 63 70 41 69 28 86 11 54 16 34 22 31 76 14 5 43 79 77 +Card 90: 10 49 37 75 89 18 62 16 65 13 | 8 67 79 40 27 23 15 56 69 71 5 85 87 88 14 74 22 19 64 98 93 35 18 82 31 +Card 91: 73 28 59 31 18 92 69 84 38 52 | 86 70 65 90 53 95 45 33 16 94 23 71 25 34 26 98 13 87 55 8 1 49 6 93 63 +Card 92: 18 60 22 23 16 6 88 4 32 44 | 37 88 46 75 97 6 22 9 5 18 92 32 16 4 49 82 13 60 44 26 28 86 8 12 23 +Card 93: 14 39 72 74 69 9 4 13 57 7 | 22 6 96 21 23 80 50 83 55 81 30 1 79 92 34 32 95 91 11 76 85 12 73 99 89 +Card 94: 38 18 52 85 43 3 89 63 78 77 | 78 35 89 77 96 27 38 46 3 58 84 37 85 4 13 52 80 7 21 50 63 42 86 28 43 +Card 95: 72 18 32 20 23 9 43 97 71 30 | 21 29 14 50 5 48 35 15 58 75 24 73 81 88 82 13 98 86 26 33 70 64 96 11 90 +Card 96: 36 27 25 77 60 63 49 1 39 31 | 29 78 5 67 77 24 71 59 22 73 6 69 99 88 37 25 21 47 42 61 2 40 26 45 23 +Card 97: 40 74 36 19 92 51 78 44 96 20 | 18 98 69 94 73 40 82 45 38 44 78 58 57 32 99 14 34 63 35 92 3 83 4 84 75 +Card 98: 57 55 61 60 77 56 50 33 48 47 | 61 77 33 86 75 47 65 50 48 84 10 55 14 28 19 53 3 46 83 31 1 51 89 56 57 +Card 99: 93 47 74 10 37 90 76 1 40 54 | 62 72 8 28 79 84 23 75 2 45 96 32 16 71 56 14 13 63 78 30 12 55 65 46 91 +Card 100: 15 33 70 46 11 23 24 69 47 5 | 6 68 69 86 55 3 50 43 45 75 36 97 91 20 15 77 21 23 17 71 70 82 42 35 9 +Card 101: 40 41 98 7 73 21 47 68 59 1 | 11 79 77 37 48 96 92 30 18 24 31 88 49 99 14 23 82 35 42 16 22 84 8 75 32 +Card 102: 92 51 37 63 18 54 28 58 40 4 | 10 94 9 42 64 11 91 23 50 30 90 81 74 77 65 24 49 60 19 70 79 83 76 72 99 +Card 103: 66 62 18 43 33 50 51 30 22 63 | 20 68 54 91 55 14 1 31 71 38 80 86 81 87 89 53 42 83 65 64 30 73 6 61 2 +Card 104: 2 86 13 94 18 9 74 35 49 91 | 82 21 12 51 25 10 89 6 73 95 2 16 83 36 49 64 3 87 41 78 27 98 67 56 7 +Card 105: 51 42 19 18 31 2 29 80 99 65 | 27 55 14 37 52 11 25 5 30 73 41 32 76 28 50 69 88 66 22 74 40 21 13 35 90 +Card 106: 6 19 88 46 69 13 49 20 63 31 | 47 32 72 78 79 53 55 75 98 16 76 52 93 17 27 77 74 45 44 60 10 91 3 87 30 +Card 107: 11 42 78 2 9 91 46 51 68 88 | 30 7 18 76 94 87 50 57 73 14 54 36 80 59 71 61 20 64 5 44 55 93 27 74 24 +Card 108: 4 79 42 25 54 92 93 88 90 81 | 86 92 79 4 52 58 3 65 95 14 42 59 15 81 12 39 90 25 98 49 38 63 27 84 88 +Card 109: 65 16 49 63 6 37 48 75 77 19 | 16 73 6 25 14 28 27 75 49 11 61 77 76 19 85 95 63 37 33 88 48 22 65 72 31 +Card 110: 83 63 27 82 72 40 70 35 12 86 | 14 96 39 40 72 56 8 83 63 43 42 86 91 58 48 70 3 73 22 35 82 33 29 31 12 +Card 111: 36 31 68 37 83 23 9 39 12 26 | 80 92 71 20 48 37 53 32 75 31 83 58 9 26 77 52 42 68 70 7 72 36 23 87 50 +Card 112: 94 61 81 68 89 42 52 92 74 39 | 94 89 15 76 86 92 65 57 84 2 21 81 49 68 42 39 90 31 13 27 69 61 3 74 52 +Card 113: 68 9 32 67 96 43 14 15 28 48 | 2 81 58 90 45 89 53 34 39 7 46 55 20 69 25 66 17 54 44 19 93 23 92 26 10 +Card 114: 25 77 57 50 59 16 46 80 2 14 | 58 14 78 81 8 75 21 45 50 67 55 1 51 92 20 25 86 32 72 54 65 44 38 91 70 +Card 115: 11 10 76 79 84 82 16 14 43 6 | 84 59 20 63 79 33 23 47 40 17 48 80 76 25 83 16 82 89 6 11 10 97 44 43 14 +Card 116: 21 1 37 82 29 36 57 76 68 63 | 86 38 20 14 36 8 7 31 68 21 56 1 63 26 28 57 96 54 29 82 37 76 61 71 40 +Card 117: 4 7 73 26 78 49 22 11 74 35 | 76 26 57 22 66 36 73 35 16 77 87 49 32 54 92 43 7 15 20 38 8 82 29 78 11 +Card 118: 58 12 45 87 44 90 48 72 77 66 | 34 57 66 52 90 98 4 99 21 80 8 3 18 45 79 23 50 10 43 62 54 60 39 29 33 +Card 119: 58 97 56 38 78 75 84 99 7 32 | 92 33 78 72 7 84 64 18 38 43 27 32 21 99 85 40 58 93 97 13 3 75 56 25 46 +Card 120: 40 31 79 63 24 20 11 56 92 32 | 63 32 92 22 1 30 79 20 58 53 64 24 56 36 81 6 49 48 17 26 73 83 47 3 8 +Card 121: 51 39 2 99 40 21 4 8 14 46 | 11 29 41 74 55 73 16 95 21 30 85 81 2 76 59 99 9 51 58 8 44 43 61 27 25 +Card 122: 29 76 10 60 87 27 35 65 37 59 | 59 53 46 17 1 48 36 88 95 85 13 41 67 31 90 39 99 24 51 11 84 42 96 91 92 +Card 123: 99 34 55 8 23 83 28 26 21 54 | 99 8 2 10 26 76 11 52 95 73 38 74 23 92 59 57 71 56 1 13 93 87 43 4 70 +Card 124: 75 96 37 43 92 85 68 78 18 4 | 71 43 78 96 92 62 76 19 39 21 52 29 36 93 81 33 53 2 10 69 82 87 14 85 68 +Card 125: 11 32 49 86 21 95 94 64 77 23 | 53 25 9 94 75 21 10 35 95 81 39 41 90 18 45 43 78 73 63 56 27 74 46 17 85 +Card 126: 8 64 16 62 90 93 98 27 57 4 | 39 89 62 42 60 33 90 3 44 32 8 13 24 85 5 93 68 55 73 22 4 52 28 58 12 +Card 127: 22 52 46 90 56 44 84 62 48 8 | 46 86 7 72 80 58 38 76 53 12 83 22 15 60 84 14 33 17 52 49 88 93 36 4 71 +Card 128: 49 31 89 7 43 41 27 58 74 72 | 92 24 40 95 80 84 2 19 70 29 83 69 42 17 39 67 97 98 32 56 23 59 21 5 68 +Card 129: 92 50 77 38 85 25 5 72 34 84 | 39 38 55 26 58 83 75 70 80 94 42 9 12 69 29 88 50 3 62 96 13 48 93 44 22 +Card 130: 45 23 32 47 89 28 9 95 94 14 | 53 78 75 3 50 29 65 60 1 98 15 13 36 71 52 21 66 19 73 67 91 37 76 26 56 +Card 131: 70 27 15 12 83 23 96 57 90 77 | 14 34 88 74 59 68 94 44 99 39 40 78 47 17 43 42 80 9 73 93 41 25 71 22 75 +Card 132: 16 32 43 64 77 1 14 78 97 98 | 78 97 64 75 52 98 13 81 16 57 3 9 14 83 32 28 56 58 1 43 87 12 77 24 31 +Card 133: 95 53 4 45 36 20 77 60 8 49 | 2 62 83 20 53 95 57 86 8 45 38 63 49 82 85 26 36 60 89 81 92 51 54 4 99 +Card 134: 95 23 88 8 52 67 46 15 36 55 | 74 44 67 8 94 88 82 46 6 34 64 23 36 14 19 91 15 72 98 56 55 95 65 13 52 +Card 135: 27 40 81 65 23 49 89 67 4 32 | 75 32 8 40 16 27 38 54 48 67 22 42 85 57 4 97 76 81 82 28 55 65 2 72 23 +Card 136: 7 35 1 24 95 80 25 4 75 37 | 73 28 64 72 56 66 55 29 52 2 80 98 11 41 16 78 75 89 35 12 85 69 24 42 39 +Card 137: 19 38 84 95 77 68 50 70 16 17 | 71 69 30 27 86 7 35 96 33 74 20 93 36 47 6 55 29 32 78 72 58 46 21 99 9 +Card 138: 97 58 41 82 43 64 26 81 2 36 | 55 79 30 88 96 99 34 82 25 6 71 44 54 77 91 11 90 80 76 40 92 69 64 29 15 +Card 139: 41 27 9 87 98 24 72 58 2 88 | 93 72 58 89 34 23 24 48 49 98 78 50 87 64 2 14 85 21 62 75 88 60 41 53 16 +Card 140: 79 92 45 91 75 2 1 57 66 40 | 42 82 45 28 75 91 1 11 63 17 20 54 27 92 48 40 12 57 69 66 2 21 19 88 79 +Card 141: 33 4 49 55 78 9 61 83 58 50 | 50 9 94 83 98 78 14 66 67 61 71 4 72 39 49 40 29 30 36 16 47 3 58 19 33 +Card 142: 80 32 49 19 43 42 50 86 97 87 | 42 15 71 58 18 85 80 19 97 86 32 62 95 44 56 50 83 28 51 34 33 43 36 87 49 +Card 143: 76 89 44 30 69 84 47 85 42 23 | 54 17 16 52 86 48 81 92 1 7 78 64 66 59 21 55 36 58 46 37 6 61 89 72 82 +Card 144: 22 9 57 50 38 82 66 70 92 37 | 71 18 63 27 87 34 23 13 39 92 77 60 74 46 50 48 57 54 66 22 59 83 44 9 70 +Card 145: 56 90 36 66 70 16 73 62 4 37 | 18 34 96 7 47 65 99 56 58 75 85 31 36 3 90 70 5 66 83 62 73 16 55 37 4 +Card 146: 68 59 27 32 62 43 25 22 42 3 | 67 68 59 70 98 16 8 25 24 22 44 53 63 11 6 65 54 74 81 32 91 50 13 62 99 +Card 147: 21 95 4 18 23 68 83 36 29 3 | 94 42 90 33 50 39 41 66 58 8 96 83 15 85 56 93 14 99 67 37 5 61 24 4 3 +Card 148: 13 22 23 39 61 17 50 28 25 19 | 86 92 67 42 85 22 17 19 7 5 39 55 47 20 64 25 50 66 31 30 61 41 18 89 74 +Card 149: 24 79 8 18 15 97 95 13 33 89 | 72 18 13 85 89 49 47 1 11 84 40 50 44 71 15 53 43 26 8 86 23 22 83 21 97 +Card 150: 98 78 63 19 91 86 1 9 55 35 | 41 33 95 85 83 20 66 23 86 94 8 87 43 37 71 58 21 14 96 3 29 6 39 53 32 +Card 151: 47 78 1 40 26 97 61 73 24 21 | 59 60 94 4 52 42 92 19 23 57 82 88 70 45 43 96 7 72 26 58 71 6 16 53 8 +Card 152: 3 79 50 95 26 91 66 60 71 53 | 12 96 93 92 49 5 9 76 30 8 23 58 63 73 94 10 19 46 39 55 33 87 18 78 86 +Card 153: 2 55 64 32 42 68 63 52 50 90 | 60 20 30 16 98 85 1 35 97 33 64 65 79 12 51 78 48 49 86 50 57 99 3 10 46 +Card 154: 4 72 77 78 27 68 37 57 82 91 | 38 39 36 23 43 53 71 24 63 64 89 80 49 97 60 47 21 90 93 48 70 86 65 66 3 +Card 155: 90 34 33 91 74 28 36 4 5 39 | 51 23 30 73 37 97 99 25 32 54 67 52 75 48 38 78 42 35 13 6 81 63 49 83 80 +Card 156: 38 8 26 2 43 32 72 45 29 5 | 77 89 32 45 73 34 23 80 1 78 5 86 19 38 7 59 75 29 8 43 26 72 20 12 2 +Card 157: 42 20 82 74 94 44 54 33 69 93 | 94 98 34 54 20 68 82 18 13 53 33 67 22 42 72 16 62 6 25 17 46 56 87 9 7 +Card 158: 41 46 13 9 93 48 65 76 3 4 | 10 67 53 57 44 18 47 13 98 59 6 52 5 91 17 54 97 61 68 26 25 42 40 72 22 +Card 159: 73 1 50 18 66 97 12 93 41 80 | 12 80 36 41 53 1 50 18 19 75 3 40 39 16 83 85 66 73 35 70 97 25 56 67 93 +Card 160: 86 47 9 35 3 85 33 53 99 50 | 44 55 12 43 86 13 20 31 3 37 33 28 9 41 98 39 35 58 19 29 25 1 82 67 71 +Card 161: 68 93 52 43 62 15 66 33 53 84 | 27 44 37 39 50 71 63 94 20 79 62 38 42 72 12 33 85 9 43 93 83 68 28 47 45 +Card 162: 54 43 38 6 50 80 72 41 78 92 | 92 73 55 15 34 61 79 57 72 71 53 83 50 41 47 60 10 58 67 36 69 2 63 84 5 +Card 163: 58 52 14 99 77 51 70 16 35 57 | 60 51 34 86 92 66 10 93 99 16 67 27 47 19 35 61 58 4 9 28 82 84 42 38 43 +Card 164: 9 19 34 3 38 46 74 85 42 87 | 68 71 70 98 63 84 10 59 16 76 91 18 36 4 60 77 97 80 64 88 95 66 94 58 37 +Card 165: 46 68 72 82 41 79 28 6 19 23 | 88 74 16 36 44 19 46 63 85 77 94 38 42 28 21 26 70 66 1 51 9 45 49 20 6 +Card 166: 94 97 38 52 45 84 81 71 49 22 | 86 66 45 40 21 58 6 82 29 87 38 68 20 96 95 49 4 77 25 36 32 51 18 94 48 +Card 167: 47 98 46 63 38 23 57 61 31 96 | 63 44 68 56 67 26 27 7 10 93 79 50 4 48 42 9 19 5 23 11 47 52 40 88 58 +Card 168: 36 59 73 99 8 49 63 19 34 74 | 24 30 98 46 65 95 91 14 7 37 87 57 40 67 16 94 66 93 12 82 48 28 88 90 58 +Card 169: 34 48 11 54 74 40 13 71 86 76 | 7 65 66 23 95 45 27 42 47 60 20 92 28 84 50 73 2 80 41 99 77 62 17 21 85 +Card 170: 67 6 17 58 51 2 19 72 33 41 | 34 20 46 35 29 89 12 77 37 97 88 4 98 44 82 39 38 15 32 48 63 65 68 21 93 +Card 171: 63 1 50 71 14 33 78 85 40 99 | 40 32 54 69 4 93 85 1 99 50 71 78 57 22 63 5 14 38 33 72 16 24 29 64 13 +Card 172: 33 52 35 85 57 49 60 11 80 43 | 39 92 94 83 49 81 82 79 97 5 72 33 87 80 63 52 96 53 1 43 35 60 85 57 11 +Card 173: 33 40 92 88 97 77 20 84 27 23 | 58 33 12 27 34 92 46 23 13 62 77 82 43 54 40 64 37 96 15 84 60 88 20 97 1 +Card 174: 4 6 66 57 77 24 59 50 9 46 | 63 57 2 60 4 89 88 46 24 14 5 66 16 59 11 13 64 39 38 92 65 44 77 17 79 +Card 175: 55 82 61 80 67 89 90 93 43 1 | 7 3 84 23 14 69 47 35 57 10 95 99 64 63 42 93 96 6 53 72 29 33 18 56 83 +Card 176: 70 7 30 29 66 82 8 24 89 11 | 9 67 86 87 22 76 50 51 40 21 6 98 94 17 12 74 33 34 55 20 53 99 1 80 52 +Card 177: 78 14 51 53 26 44 36 2 33 23 | 53 26 48 24 5 88 33 90 36 22 29 89 51 45 70 44 23 2 73 91 57 92 78 47 14 +Card 178: 19 75 43 85 35 45 93 59 57 7 | 57 32 12 45 76 59 71 85 74 46 69 25 86 10 50 44 79 95 93 49 63 24 82 33 73 +Card 179: 35 18 9 3 88 62 83 98 61 41 | 41 70 64 48 31 61 45 46 15 99 69 51 98 28 87 17 30 26 24 52 29 71 60 38 66 +Card 180: 13 20 97 73 94 22 80 40 47 85 | 41 30 22 11 65 87 69 23 58 27 59 57 96 55 82 20 79 76 85 3 89 13 8 25 94 +Card 181: 14 74 36 86 59 49 69 24 65 28 | 93 24 57 83 34 62 80 85 74 36 23 9 13 45 52 67 64 26 15 69 95 21 43 38 77 +Card 182: 41 88 35 24 7 6 11 79 8 56 | 25 78 66 69 64 44 95 81 85 48 87 26 47 63 56 3 94 86 8 52 24 73 15 20 19 +Card 183: 2 35 46 34 76 99 12 47 33 64 | 15 53 32 21 73 11 7 26 75 95 37 17 67 56 77 99 39 72 82 47 2 64 20 33 55 +Card 184: 73 43 57 65 99 86 29 32 69 53 | 4 19 89 82 48 94 18 53 17 64 45 85 26 52 97 43 47 1 41 90 65 72 46 20 31 +Card 185: 81 71 51 68 27 22 63 76 85 3 | 84 20 91 48 47 98 13 30 83 64 93 26 50 78 66 77 9 97 32 12 90 41 74 52 43 +Card 186: 76 27 92 85 62 60 75 11 65 70 | 48 51 58 99 40 52 50 10 95 1 46 21 67 78 86 36 55 14 84 28 12 18 8 42 53 +Card 187: 88 55 79 69 45 73 16 21 5 11 | 95 24 32 59 96 37 87 7 28 89 33 82 35 60 83 20 43 75 57 80 1 9 52 31 36 +Card 188: 61 32 89 34 13 46 66 42 22 91 | 74 52 2 85 82 57 8 41 26 6 10 38 95 64 90 79 3 60 98 76 45 94 51 70 28 diff --git a/src/day4.rs b/src/day4.rs new file mode 100644 index 0000000..922cd4c --- /dev/null +++ b/src/day4.rs @@ -0,0 +1,125 @@ +#[derive(Debug)] +struct Scratchcard { + id: u32, + numbers: Vec, + winning_numbers: Vec, +} + +impl std::str::FromStr for Scratchcard { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + println!("s = {}", s); + let mut result = Scratchcard { id: 0, numbers: vec![], winning_numbers: vec![] }; + let mut state = 0; + for tok in s.split(&[' ', ':'][..]) { + println!("state = {}, tok = {}", state, tok); + if tok.trim().is_empty() { + continue; + } + + if state == 0 { + if tok == "Card" { + continue; + } + if let Ok(id) = tok.parse::() { + result.id = id; + state = 1; + } else { + return Err("invalid card id") + } + } else if state == 1 { + if let Ok(number) = tok.parse::() { + result.numbers.push(number); + } else if tok == "|" { + state = 2; + } else { + return Err("invalid input") + } + } else if state == 2 { + if let Ok(number) = tok.parse::() { + result.winning_numbers.push(number); + } else { + return Err("invalid input") + } + } + } + if result.id != 0 && !result.numbers.is_empty() && !result.winning_numbers.is_empty() { + println!("result = {:?}", result); + return Ok(result) + } + Err("invalid input") + } +} + +impl Scratchcard { + fn count_points(&self) -> u32 { + let mut winning = 0; + for number in &self.numbers { + if self.winning_numbers.contains(number) { + winning += 1; + } + } + if winning == 0 { + return 0; + } + 2_u32.pow(winning - 1) + } +} + +#[derive(Debug)] +struct PileOfScratchcards { + cards: Vec, +} + +impl std::str::FromStr for PileOfScratchcards { + type Err = (); + + fn from_str(s: &str) -> Result { + let mut cards = vec![]; + for line in s.lines() { + if let Ok(card) = line.parse::() { + cards.push(card); + } + } + Ok(PileOfScratchcards { cards }) + } +} + +impl PileOfScratchcards { + fn count_points(&self) -> u32 { + let mut points = 0; + for card in &self.cards { + points += card.count_points(); + } + points + } +} + +pub fn main() { + match std::fs::read_to_string("day4.input") { + Ok(input) => { + if let Ok(scratchcards) = input.parse::() { + println!("points = {}", scratchcards.count_points()); + } + }, + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn count_points_example() { + static DATA: &str = "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 +Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 +Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 +Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 +Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 +Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"; + let scratchcards = DATA.parse::().unwrap(); + assert_eq!(scratchcards.count_points(), 13); + } +} diff --git a/src/main.rs b/src/main.rs index 35459aa..8c31528 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day3; +mod day4; fn main() { - day3::main() + day4::main() } From da236df7459bf96cd49e603ff2a9d1abfc215dbf Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 5 Dec 2023 21:39:58 +0100 Subject: [PATCH 071/120] Day 4, part 2: Distribute the winnings --- src/day4.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/day4.rs b/src/day4.rs index 922cd4c..bb8ea2e 100644 --- a/src/day4.rs +++ b/src/day4.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + #[derive(Debug)] struct Scratchcard { id: u32, @@ -53,13 +55,18 @@ impl std::str::FromStr for Scratchcard { } impl Scratchcard { - fn count_points(&self) -> u32 { + fn count_winning(&self) -> u32 { let mut winning = 0; for number in &self.numbers { if self.winning_numbers.contains(number) { winning += 1; } } + winning + } + + fn count_points(&self) -> u32 { + let winning = self.count_winning(); if winning == 0 { return 0; } @@ -94,6 +101,29 @@ impl PileOfScratchcards { } points } + + fn count_cards_part_2(&self) -> usize { + let mut dups = HashMap::::new(); + let mut cards = 0; + for card in &self.cards { + let mut cards_of_id = 1; + if let Some(dups_of_id) = dups.get(&card.id) { + cards_of_id += dups_of_id; + } + println!("cards of id {} = {}", card.id, cards_of_id); + cards += cards_of_id; + + // Distribute the winning cards further + let winning = card.count_winning(); + println!("winning = {}", winning); + for i in 1..=winning { + dups.entry(card.id + i) + .and_modify(|e| *e += cards_of_id ) + .or_insert(cards_of_id); + } + } + cards + } } pub fn main() { @@ -101,6 +131,7 @@ pub fn main() { Ok(input) => { if let Ok(scratchcards) = input.parse::() { println!("points = {}", scratchcards.count_points()); + println!("cards = {}", scratchcards.count_cards_part_2()); } }, Err(reason) => println!("error = {}", reason) @@ -122,4 +153,16 @@ Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"; let scratchcards = DATA.parse::().unwrap(); assert_eq!(scratchcards.count_points(), 13); } + + #[test] + fn count_cards_part_2() { + static DATA: &str = "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 +Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 +Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 +Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 +Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 +Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"; + let scratchcards = DATA.parse::().unwrap(); + assert_eq!(scratchcards.count_cards_part_2(), 30); + } } From 4774cdcacd338ead195ac32051713ce43067ff10 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Wed, 6 Dec 2023 09:37:50 +0100 Subject: [PATCH 072/120] Day 5, part 1: Rust's borrow-ing/move-ing/... is _annoying_. --- .vscode/launch.json | 4 +- day5.input | 213 ++++++++++++++++++++++++++++++++++++++++++++ src/day5.rs | 207 ++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 +- 4 files changed, 424 insertions(+), 4 deletions(-) create mode 100644 day5.input create mode 100644 src/day5.rs diff --git a/.vscode/launch.json b/.vscode/launch.json index b138b62..ee63023 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,13 +1,13 @@ { "configurations": [ { - "type": "cppdbg", + "type": "lldb", "request": "launch", "name": "run adventofcode", "program": "${workspaceFolder}/target/debug/adventofcode", "args": [], "cwd": "${workspaceFolder}", - "sourceFileMap": {}, + "sourceLanguages": ["rust"], } ] } diff --git a/day5.input b/day5.input new file mode 100644 index 0000000..eeee701 --- /dev/null +++ b/day5.input @@ -0,0 +1,213 @@ +seeds: 3139431799 50198205 3647185634 110151761 2478641666 139825503 498892555 8913570 961540761 489996751 568452082 100080382 907727477 42158689 1617552130 312026427 342640189 97088268 2049289560 336766062 + +seed-to-soil map: +1615836342 1401909974 23067952 +785532007 269485885 88937774 +3019002892 2773729385 10470414 +4202163101 2747292152 26437233 +3183210415 4217634159 77333137 +2847460091 3211730218 136699600 +2455891790 3791729773 70553041 +3260543552 2581343101 165949051 +3840286095 2849853212 361877006 +4228600334 2361239030 66366962 +1594559581 1077839137 21276761 +380069408 165017790 44262617 +3598718222 1894384162 241567873 +0 1424977926 190757551 +1894384162 2810496375 39356837 +424332025 606264721 196539291 +3521487829 2221977524 77230393 +742681934 69797365 36566707 +1638904294 1615735477 139190145 +1335949488 0 69797365 +779248641 802804012 6283366 +2638766896 4008940964 208693195 +250963029 1142644585 70452661 +1933740999 3470280789 321448984 +190757551 209280407 60205478 +1778094439 1099115898 43528687 +2255189983 3348429818 121850971 +1000500225 809087378 268751759 +1269251984 1754925622 66697504 +874469781 358423659 126030444 +2526444831 2135952035 86025489 +2439072067 3992121241 16819723 +3426492603 3897126015 94995226 +1405746853 1213097246 188812728 +321415690 106364072 58653718 +2984159691 3862282814 34843201 +2377040954 2299207917 62031113 +3029473306 2427605992 153737109 +2612470320 2784199799 26296576 +620871316 484454103 121810618 + +soil-to-fertilizer map: +4245401761 2352458099 28057201 +2099789767 3998256334 14950546 +3446056574 2749719529 135349925 +890092371 1379309857 42097049 +953714890 896502554 10335567 +3115342240 2380515300 218129381 +3333471621 3885671381 112584953 +663999152 0 226093219 +1873325002 727305635 169196919 +2042521921 1328150912 51158945 +3581406499 4034715214 260252082 +500989478 564295961 163009674 +4273458962 4013206880 21508334 +3992733429 2099789767 164092891 +4156826320 2263882658 88575441 +3841658581 2598644681 151074848 +1094703999 226093219 21270249 +1708571521 399542480 164753481 +964050457 247363468 130653542 +1236290130 1421406906 171284482 +0 1592691388 500989478 +932189420 378017010 21525470 +2114740313 2885069454 1000601927 +1115974248 1207835030 120315882 +1407574612 906838121 300996909 + +fertilizer-to-water map: +3217858280 3761663130 355893932 +2319366035 2401839275 72374872 +1962726423 909927230 105011330 +2115307878 441322644 204058157 +2095064202 1824085445 20243676 +110580631 329763915 34129824 +2573484127 2701101998 225220022 +1780224111 2342656863 59182412 +1717605398 1571533532 62618713 +3589165621 3062909078 75538793 +842280446 1871096488 471560375 +409726333 0 243114563 +397401582 760576019 12324751 +0 667815878 92760141 +3990305711 2926322020 5981819 +251664023 1741105813 32320840 +2072629125 645380801 22435077 +92760141 363893739 17820490 +2798704149 3138447871 156185660 +3664704414 2573484127 127617871 +1839406523 381714229 59608415 +283984863 1844329121 26767367 +1313840821 1176023584 27579684 +2391740907 1790738543 33346902 +3929650615 4234312200 60655096 +3996287530 3557602002 204061128 +1402088224 772900770 137026460 +1911435456 2474214147 51290967 +1539114684 1393042818 178490714 +3573752212 4117557062 15413409 +1341420505 1014938560 60667719 +3792322285 4132970471 6723091 +4200348658 4139693562 80082634 +652840896 1203603268 189439550 +310752230 243114563 86649352 +2425087809 1075606279 100417305 +1899014938 1773426653 12420518 +2067737753 1785847171 4891372 +3799045376 2932303839 130605239 +2954889809 3294633531 262968471 +4280431292 4219776196 14536004 +144710455 1634152245 106953568 + +water-to-light map: +1071107509 759231097 26724064 +1293599454 642189614 64567949 +3147690498 1633749175 71376364 +3487999223 4080968704 155844998 +1700873635 2097781236 292450760 +1146121952 1950303734 147477502 +2864027062 1470573702 75076585 +2507471274 3021419800 175807670 +2939103647 922829268 123372939 +2826742681 2551285626 37284381 +719212681 1821763210 100196810 +4236813702 4292227071 2740225 +3643844221 3837685117 243283587 +209103905 785955161 52302440 +100332146 752700417 6530680 +1478192138 3229160565 10342236 +1358167403 3239502801 94242072 +3219066862 706757563 45942854 +3062476586 1358475140 29661777 +819409491 2390231996 26561329 +4195136152 3511184798 41677550 +1488534374 1046202207 35444248 +3887127808 3552862348 284822769 +2188804057 1705125539 116637671 +0 309410320 100332146 +1117778238 1921960020 28343714 +261406345 3333744873 74978759 +2100705169 1545650287 88098888 +3450098653 3473284228 37900570 +2742067948 1273800407 84674733 +2305441728 107380774 202029546 +3265009716 1130086491 143713916 +1993324395 0 107380774 +1523978622 465294601 176895013 +106862826 2588570007 102241079 +2683278944 864040264 58789004 +4239553927 4236813702 55413369 +1097831573 1081646455 19946665 +524293914 1101593120 28493371 +336385104 2833510990 187908810 +552787285 3197227470 31933095 +845970820 2690811086 142699904 +988670724 1388136917 82436785 +1452409475 838257601 25782663 +3092138363 409742466 55552135 +584720380 2416793325 134492301 +4171950577 3450098653 23185575 + +light-to-temperature map: +2906633798 3843376160 451591136 +1332454428 1190958320 69004583 +1837712164 0 353313230 +494809338 353313230 376619264 +871428602 729932494 461025826 +1401459011 1754772241 373416033 +3976747173 3375456648 91164221 +3495346659 3466620869 376755291 +0 1259962903 494809338 +2608238358 2459541635 298395440 +3907558614 2984992977 69188559 +3872101950 2286963246 35456664 +4067911394 2757937075 227055902 +3358224934 2322419910 137121725 +2286963246 3054181536 321275112 +1774875044 2128188274 62837120 + +temperature-to-humidity map: +3966168141 3406025946 214996780 +4181164921 3292223571 113802375 +1493139015 1471031672 367564898 +1423475871 1838596570 69663144 +0 479293006 226560784 +2500785470 2859072453 433151118 +3197453551 2500785470 96923792 +758446483 1237739489 233292183 +991738666 0 278789291 +3555740534 3884539689 410427607 +3294377343 2597709262 261363191 +226560784 705853790 531885699 +1860703913 305742584 20602508 +2933936588 3621022726 263516963 +1881306421 278789291 26953293 +1270527957 326345092 152947914 + +humidity-to-location map: +848612454 2250862530 61410922 +910023376 3689675651 35197452 +3724873103 3865027106 240221283 +483883727 3324946924 364728727 +0 1766978803 483883727 +1957894300 561533 922927950 +945220828 2590144784 734802140 +2880822250 0 561533 +3447014853 1489120553 277858250 +2881383783 923489483 565631070 +3965094386 3724873103 140154003 +1680022968 2312273452 277871332 diff --git a/src/day5.rs b/src/day5.rs new file mode 100644 index 0000000..dcf8648 --- /dev/null +++ b/src/day5.rs @@ -0,0 +1,207 @@ +use std::{collections::HashMap, cmp::min}; + +#[derive(Debug)] +struct AlmanacRange { + destination_min: usize, + source_min: usize, + length: usize, +} + +impl AlmanacRange { + fn new(destination_min: usize, source_min: usize, length: usize) -> Self { + AlmanacRange { destination_min, source_min, length } + } + + fn lookup(&self, key: usize) -> Option { + if key < self.source_min { + return None; + } + if key >= self.source_min + self.length { + return None; + } + + let result = self.destination_min + (key - self.source_min); + Some(result) + } +} + +/// A mapping in the almanac. +#[derive(Debug)] +struct AlmanacMap { + name: String, + ranges: Vec, +} + +impl AlmanacMap { + fn new(name: &str) -> Self { + AlmanacMap { name: String::from(name), ranges: vec![] } + } + + fn append_range(&mut self, destination_min: usize, source_min: usize, length: usize) { + self.ranges.push(AlmanacRange::new(destination_min, source_min, length)); + } + + fn lookup(&self, key: usize) -> usize { + println!("{}::lookup({})", self.name, key); + for range in &self.ranges { + if let Some(mapped) = range.lookup(key) { + return mapped; + } + } + key + } +} + +#[derive(Debug)] +struct Almanac { + seeds: Vec, + maps: HashMap +} + +impl std::str::FromStr for Almanac { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let lines = s.lines().collect::>(); + + // First line: seeds. + let seeds_line = lines[0].split_once(':'); + if seeds_line.is_none() { + return Err("invalid line: no delimiter"); + } else if seeds_line.unwrap().0 != "seeds" { + return Err("invalid line: no seeds keyword"); + } + println!("parsing seeds {}", seeds_line.unwrap().1); + let seeds = seeds_line.unwrap().1 + .split(' ') + .filter_map(|s| s.parse::().ok()).collect::>(); + + // Parse the remaining lines as maps: A title line identifying the map name (`X-to-Y map:`), followed + // by 1 or more lines of the form `destination_min source_min length`. + let mut maps = HashMap::::new(); + let mut map: Option = None; + for line in &lines[1..] { + if line.trim().is_empty() { + if let Some(m) = map.take() { + maps.insert(m.name.clone(), m); + } + continue + } + + if map.is_some() { + let parts = line.split(' ').collect::>(); + if parts.len() != 3 { + return Err("invalid map line"); + } + let destination_min = parts[0].parse::().unwrap(); + let source_min = parts[1].parse::().unwrap(); + let length = parts[2].parse::().unwrap(); + map.as_mut().unwrap().append_range( destination_min, source_min, length); + } else if let Some((name, map_keyword)) = line.split_once(' ') { + if map_keyword != "map:" { + return Err("invalid line: no map keyword"); + } + map = Some(AlmanacMap::new(name)); + } else { + return Err("invalid line: expected a map"); + } + } + if let Some(m) = map.take() { + maps.insert(m.name.clone(), m); + } + Ok(Almanac { seeds, maps }) + } +} + +impl Almanac { + fn mapping(&self, from: &str, to: &str) -> Option usize + '_>> { + if from == to { + return Some(Box::new(|v| v)) + } + + println!("mapping({}, {})?", from, to); + for m in self.maps.values() { + if let Some((map_from, map_to)) = m.name.split_once("-to-") { + if map_from != from { + continue; + } + if let Some(result) = self.mapping(map_to, to) { + let composed = move |v| result(m.lookup(v)); + return Some(Box::new(composed)) + } + } + } + println!("[x] not found"); + None + } + + fn lowest_location(&self) -> usize { + // First we need to find a "path" from a "seed-to-" map + // to a "-to-location" map. We can then apply the same path + // for each of the seeds, and output the minimum location value. + let mut result = std::usize::MAX; + if let Some(map) =self.mapping("seed", "location") { + for i in &self.seeds { + result = min(result, map(*i)); + } + return result + } + + panic!("Cannot find a path") + } +} + +pub fn main() { + match std::fs::read_to_string("day5.input") { + Ok(input) => { + if let Ok(almanac) = input.parse::() { + println!("lowest_location = {}", almanac.lowest_location()); + } + }, + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + static DATA: &str = "seeds: 79 14 55 13 + +seed-to-soil map: +50 98 2 +52 50 48 + +soil-to-fertilizer map: +0 15 37 +37 52 2 +39 0 15 + +fertilizer-to-water map: +49 53 8 +0 11 42 +42 0 7 +57 7 4 + +water-to-light map: +88 18 7 +18 25 70 + +light-to-temperature map: +45 77 23 +81 45 19 +68 64 13 + +temperature-to-humidity map: +0 69 1 +1 0 69 + +humidity-to-location map: +60 56 37 +56 93 4"; + let almanac = DATA.parse::().unwrap(); + assert_eq!(almanac.lowest_location(), 35); + } +} diff --git a/src/main.rs b/src/main.rs index 8c31528..45ded40 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day4; +mod day5; fn main() { - day4::main() + day5::main() } From 747705a36c406f028a0db05be0ec3728b8f48d1c Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Thu, 7 Dec 2023 22:53:40 +0100 Subject: [PATCH 073/120] Day 5, part 2: Brute-force before starting to optimize. --- src/day5.rs | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/day5.rs b/src/day5.rs index dcf8648..baa78c4 100644 --- a/src/day5.rs +++ b/src/day5.rs @@ -135,14 +135,27 @@ impl Almanac { None } - fn lowest_location(&self) -> usize { + fn lowest_location(&self, use_ranges: bool) -> usize { // First we need to find a "path" from a "seed-to-" map // to a "-to-location" map. We can then apply the same path // for each of the seeds, and output the minimum location value. let mut result = std::usize::MAX; - if let Some(map) =self.mapping("seed", "location") { - for i in &self.seeds { - result = min(result, map(*i)); + if let Some(map) = self.mapping("seed", "location") { + if use_ranges { + let mut i = 0; + while i < self.seeds.len() { + let start = self.seeds[i]; + let length = self.seeds[i+1]; + i += 2; + + for j in start..start+length { + result = min(result, map(j)); + } + } + } else { + for i in &self.seeds { + result = min(result, map(*i)); + } } return result } @@ -155,7 +168,8 @@ pub fn main() { match std::fs::read_to_string("day5.input") { Ok(input) => { if let Ok(almanac) = input.parse::() { - println!("lowest_location = {}", almanac.lowest_location()); + println!("lowest_location (part 1) = {}", almanac.lowest_location(false)); + println!("lowest_location (part 2) = {}", almanac.lowest_location(true)); } }, Err(reason) => println!("error = {}", reason) @@ -166,9 +180,7 @@ pub fn main() { mod tests { use super::*; - #[test] - fn test() { - static DATA: &str = "seeds: 79 14 55 13 + static DATA: &str = "seeds: 79 14 55 13 seed-to-soil map: 50 98 2 @@ -201,7 +213,16 @@ temperature-to-humidity map: humidity-to-location map: 60 56 37 56 93 4"; + + #[test] + fn part1_example() { + let almanac = DATA.parse::().unwrap(); + assert_eq!(almanac.lowest_location(false), 35); + } + + #[test] + fn part2_example() { let almanac = DATA.parse::().unwrap(); - assert_eq!(almanac.lowest_location(), 35); + assert_eq!(almanac.lowest_location(true), 46); } } From 86973d6b60e5806fbfcd4310e477cf9a14395d9d Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 8 Dec 2023 11:12:59 +0100 Subject: [PATCH 074/120] Day 5, part 2: Simplify and then just do it. Instead of building a chain of lambdas: Just figure out the order in which to traverse the maps, and return a single lambda doing that. --- Cargo.lock | 9 +++++++ Cargo.toml | 1 + src/day5.rs | 77 ++++++++++++++++++++++++++++++++--------------------- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f26e54c..d90a9bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,3 +5,12 @@ version = 3 [[package]] name = "adventofcode" version = "0.1.0" +dependencies = [ + "muldiv", +] + +[[package]] +name = "muldiv" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956787520e75e9bd233246045d19f42fb73242759cc57fba9611d940ae96d4b0" diff --git a/Cargo.toml b/Cargo.toml index b98fdda..5979cfe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +muldiv = "1.0.1" [[bin]] name = "adventofcode" diff --git a/src/day5.rs b/src/day5.rs index baa78c4..6ce76a8 100644 --- a/src/day5.rs +++ b/src/day5.rs @@ -1,3 +1,5 @@ +extern crate muldiv; +use muldiv::MulDiv; use std::{collections::HashMap, cmp::min}; #[derive(Debug)] @@ -42,7 +44,7 @@ impl AlmanacMap { } fn lookup(&self, key: usize) -> usize { - println!("{}::lookup({})", self.name, key); + // println!("{}::lookup({})", self.name, key); for range in &self.ranges { if let Some(mapped) = range.lookup(key) { return mapped; @@ -114,53 +116,66 @@ impl std::str::FromStr for Almanac { } impl Almanac { - fn mapping(&self, from: &str, to: &str) -> Option usize + '_>> { - if from == to { - return Some(Box::new(|v| v)) - } - - println!("mapping({}, {})?", from, to); + fn find_map(&self, from: &str) -> Option<(&str, &AlmanacMap)> { for m in self.maps.values() { if let Some((map_from, map_to)) = m.name.split_once("-to-") { - if map_from != from { - continue; - } - if let Some(result) = self.mapping(map_to, to) { - let composed = move |v| result(m.lookup(v)); - return Some(Box::new(composed)) + if map_from == from { + return Some((map_to, m)) } } } - println!("[x] not found"); None } + fn mapping<'a>(&'a self, from: &'a str, to: &'a str) -> impl Fn(usize) -> usize + 'a { + let mut next_from = from; + let mut maps = vec![]; + + while next_from != to { + println!("mapping: {} -> {}", next_from, to); + if let Some((map_to, m)) = self.find_map(next_from) { + // This is the next map to follow + maps.push(m); + next_from = map_to; + } + } + + move |v| { + let mut result = v; + for m in maps.iter() { + result = m.lookup(result) + } + result + } + } + fn lowest_location(&self, use_ranges: bool) -> usize { // First we need to find a "path" from a "seed-to-" map // to a "-to-location" map. We can then apply the same path // for each of the seeds, and output the minimum location value. let mut result = std::usize::MAX; - if let Some(map) = self.mapping("seed", "location") { - if use_ranges { - let mut i = 0; - while i < self.seeds.len() { - let start = self.seeds[i]; - let length = self.seeds[i+1]; - i += 2; - - for j in start..start+length { - result = min(result, map(j)); + let map = self.mapping("seed", "location"); + if use_ranges { + let mut i = 0; + while i < self.seeds.len() { + let start = self.seeds[i]; + let length = self.seeds[i+1]; + i += 2; + + for j in 0..length { + if j % 1000 == 0 { + print!("\rscanning range {}..{}: {}%", start, start + length, (j as u64).mul_div_floor(100, length as u64).unwrap()); } + result = min(result, map(start + j)); } - } else { - for i in &self.seeds { - result = min(result, map(*i)); - } + println!() + } + } else { + for i in &self.seeds { + result = min(result, map(*i)); } - return result } - - panic!("Cannot find a path") + result } } From 901e8600d20fe7a4190daacb9a55b7fe730faf1a Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 8 Dec 2023 12:28:19 +0100 Subject: [PATCH 075/120] Day 6, part 1: Back to highschool. --- day6.input | 2 ++ src/day6.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 +-- 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 day6.input create mode 100644 src/day6.rs diff --git a/day6.input b/day6.input new file mode 100644 index 0000000..e5ef7bb --- /dev/null +++ b/day6.input @@ -0,0 +1,2 @@ +Time: 46 80 78 66 +Distance: 214 1177 1402 1024 diff --git a/src/day6.rs b/src/day6.rs new file mode 100644 index 0000000..4f53ee0 --- /dev/null +++ b/src/day6.rs @@ -0,0 +1,76 @@ +struct RaceTable { + races: Vec<(usize, usize)>, +} + +impl std::str::FromStr for RaceTable { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + if let Some((times_line, distances_line)) = s.split_once('\n') { + let times = times_line.split_ascii_whitespace().skip(1).map(|s| s.parse::()).collect::, _>>().map_err(|_| "cannot parse times")?; + let distances = distances_line.split_ascii_whitespace().skip(1).map(|s| s.parse::()).collect::, _>>().map_err(|_| "cannot parse distances")?; + if times.len() != distances.len() { + return Err("mismatch between times and distances") + } + return Ok(RaceTable { races: times.iter().zip(distances.iter()).map(|(time, distance)| (*time, *distance)).collect() }) + } + Err("cannot parse") + } +} + +impl RaceTable { + fn number_of_ways_to_beat_the_record(time: usize, distance: usize) -> usize { + // The distance is the record to beat, and we do that by by checking for each possible + // time of holding the button (x) the value of x * (time - x) > distance. + // Instead of running over the values, we can also find the two zeros of the function -x^2 - x*time - distance = 0: The number of + // times we beat the record is then floor(x2 - x1). We know that x1 is >= 0; there is a chance + // that x2 is > time, in which case we have to use time instead of x2. + // + // -x^2 + time * x - distance = 0 | * -1 + // x^2 - time * x + distance = 0 + // + // The zeros of the function are x{1,2} = time/2 +- sqrt(time^2/4 - distance). + // + // The tricky part here is that if the zero is not an integer, we have to round it up (x1) or down (x2), + // and if it is an integer we need to exclude it from the result and use the next higher/lower value. + // We can do that by adding 1 and then rounding down (x1) or subtracting 1 and then rounding up (x2). + let m = ((time * time / 4 - distance) as f32).sqrt(); + let x1 = ((time as f32) / 2.0 - m + 1_f32).floor().clamp(0_f32, time as f32); + let x2 = ((time as f32) / 2.0 + m - 1_f32).ceil().clamp(0_f32, time as f32); + let result = (x2 - x1 + 1_f32).floor() as usize; + println!("time = {}, distance = {}, m = {}, x1 = {}, x2 = {}: result = {}", time, distance, m, x1, x2, result); + result + } + + fn product(&self) -> usize { + let mut result = 1; + for (time, distance) in &self.races { + let number_of_ways = Self::number_of_ways_to_beat_the_record(*time, *distance); + result *= number_of_ways; + } + result + } +} + +pub fn main() { + match std::fs::read_to_string("day6.input") { + Ok(input) => { + if let Ok(race_table) = input.parse::() { + println!("product of number of ways to win races (part 1) = {}", race_table.product()); + } + }, + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + static DATA: &str = "Time: 7 15 30 +Distance: 9 40 200"; + assert_eq!(DATA.parse::().ok().unwrap().product(), 288); + } +} diff --git a/src/main.rs b/src/main.rs index 45ded40..9f659f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day5; +mod day6; fn main() { - day5::main() + day6::main() } From 17f410bd08f9b4f0c28e143a51dc658d5821ef17 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 8 Dec 2023 12:33:48 +0100 Subject: [PATCH 076/120] Day 6, part 2: Close, but no cookie, yet. "Too high": Question is, where ... --- src/day6.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/day6.rs b/src/day6.rs index 4f53ee0..93b83a1 100644 --- a/src/day6.rs +++ b/src/day6.rs @@ -50,6 +50,12 @@ impl RaceTable { } result } + + fn part2(&self) -> usize { + let time = self.races.iter().map(|(time, _)| format!("{}", time)).collect::>().join("").parse::().unwrap(); + let distance = self.races.iter().map(|(_, distance)| format!("{}", distance)).collect::>().join("").parse::().unwrap(); + Self::number_of_ways_to_beat_the_record(time, distance) + } } pub fn main() { @@ -57,6 +63,7 @@ pub fn main() { Ok(input) => { if let Ok(race_table) = input.parse::() { println!("product of number of ways to win races (part 1) = {}", race_table.product()); + println!("big race (part 2) = {}", race_table.part2()); } }, Err(reason) => println!("error = {}", reason) @@ -67,10 +74,16 @@ pub fn main() { mod tests { use super::*; - #[test] - fn test() { - static DATA: &str = "Time: 7 15 30 + static DATA: &str = "Time: 7 15 30 Distance: 9 40 200"; + + #[test] + fn test_part1() { assert_eq!(DATA.parse::().ok().unwrap().product(), 288); } + + #[test] + fn test_part2() { + assert_eq!(DATA.parse::().ok().unwrap().part2(), 71503); + } } From f8b1e081e533c378ab6c95adbf1aa3ee4d9f054e Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 8 Dec 2023 12:36:33 +0100 Subject: [PATCH 077/120] More precision, more good. --- src/day6.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/day6.rs b/src/day6.rs index 93b83a1..3df23a1 100644 --- a/src/day6.rs +++ b/src/day6.rs @@ -34,10 +34,10 @@ impl RaceTable { // The tricky part here is that if the zero is not an integer, we have to round it up (x1) or down (x2), // and if it is an integer we need to exclude it from the result and use the next higher/lower value. // We can do that by adding 1 and then rounding down (x1) or subtracting 1 and then rounding up (x2). - let m = ((time * time / 4 - distance) as f32).sqrt(); - let x1 = ((time as f32) / 2.0 - m + 1_f32).floor().clamp(0_f32, time as f32); - let x2 = ((time as f32) / 2.0 + m - 1_f32).ceil().clamp(0_f32, time as f32); - let result = (x2 - x1 + 1_f32).floor() as usize; + let m = ((time * time / 4 - distance) as f64).sqrt(); + let x1 = ((time as f64) / 2.0 - m + 1_f64).floor().clamp(0_f64, time as f64); + let x2 = ((time as f64) / 2.0 + m - 1_f64).ceil().clamp(0_f64, time as f64); + let result = (x2 - x1 + 1_f64).floor() as usize; println!("time = {}, distance = {}, m = {}, x1 = {}, x2 = {}: result = {}", time, distance, m, x1, x2, result); result } From 24dd25d93c88e657f862e5c4897c0d11a95e243b Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 8 Dec 2023 20:47:34 +0100 Subject: [PATCH 078/120] Day 7, part 1: Classify things, and then sort them. Biggest challenge: Making sure we consistently sort ascending or descending ... --- day7.input | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/day7.rs | 197 ++++++++++ src/main.rs | 4 +- 3 files changed, 1199 insertions(+), 2 deletions(-) create mode 100644 day7.input create mode 100644 src/day7.rs diff --git a/day7.input b/day7.input new file mode 100644 index 0000000..9ca52f2 --- /dev/null +++ b/day7.input @@ -0,0 +1,1000 @@ +AATKJ 840 +27A83 251 +6TT8T 113 +Q6T6T 693 +99K89 553 +777Q7 136 +7227J 782 +TJ2J9 837 +55578 524 +24Q49 919 +AAA2A 709 +KT972 907 +85282 886 +4432J 255 +K6K27 119 +J9Q77 820 +33K3K 48 +T8887 500 +28272 77 +38Q46 287 +KQQAQ 481 +5T2T3 280 +KQQQQ 458 +K82Q3 712 +Q5552 758 +4K87K 174 +7QQJQ 331 +29233 96 +79KA3 65 +J9893 546 +Q5A39 842 +K4K7K 437 +T555T 215 +9A7AA 162 +32AA2 374 +8J222 134 +38376 583 +J5222 962 +J65A9 883 +36338 956 +Q654T 107 +K4KKK 169 +A9A76 710 +9KQ78 183 +88753 577 +K997J 539 +4QA88 914 +K5T3A 401 +8K77K 619 +8888J 400 +TATAT 58 +8T436 279 +3Q28A 659 +3KK4J 54 +QQJ59 903 +44777 779 +53336 477 +22J33 930 +TQ6T2 923 +475TK 633 +5KJ45 980 +47TK6 50 +K8KKK 453 +2TJKA 39 +TJ6K6 380 +4J888 311 +27277 317 +2A2A5 213 +TT7T3 365 +22555 858 +789QQ 421 +937KT 791 +89KT6 732 +3KKKJ 703 +A2T22 896 +6467J 489 +72878 863 +46J5J 283 +TATA6 71 +Q4967 941 +7JT55 232 +9TQQQ 785 +55445 835 +K68KK 256 +TT33T 72 +2A2AQ 435 +9643K 436 +J3282 95 +88TQQ 767 +Q8788 250 +QQ949 62 +4T552 448 +JJ8QQ 476 +2JT22 900 +73T7T 648 +QQQJJ 795 +98A35 589 +94444 479 +44486 465 +7TK86 521 +2JK45 761 +556KT 492 +94K99 144 +2QJ32 637 +66226 538 +933TA 248 +T2234 419 +QAA26 35 +K63K3 853 +5KJK9 970 +KK4QK 636 +8TTTT 69 +5T7J8 161 +239A4 91 +3T823 182 +24A8K 407 +K5A92 330 +KK9K3 599 +2244J 284 +AAJ5Q 794 +44A84 472 +KK2J3 597 +6QQJ6 547 +TAAT4 668 +J4444 827 +QAJ22 200 +KT5J5 80 +7K3J9 517 +3A33T 762 +TT66T 154 +6K972 569 +6378Q 593 +2AQA9 460 +2KKAA 516 +AK45A 978 +QAAA8 568 +83478 234 +33737 491 +Q9Q43 977 +QKQQ7 523 +9T24A 609 +88997 355 +KAKAA 651 +87Q77 665 +JK7A4 268 +68586 44 +4345J 931 +Q29A9 871 +3479K 774 +3TK65 189 +9249Q 319 +27J2Q 656 +333J9 667 +6TJ66 681 +82T96 738 +K3K39 14 +74JK9 297 +8A88A 798 +AT869 987 +9TAT9 996 +33939 684 +4424J 117 +44AJA 422 +646AA 358 +K3T83 218 +KK7K7 495 +A6A6J 731 +3QQ97 381 +43ATK 484 +K9965 982 +9J9JJ 392 +Q2QQQ 420 +58588 433 +9Q955 862 +88777 246 +669J7 438 +9AA2A 733 +8A9K6 175 +Q25JK 459 +JJ2K8 439 +T8K9T 195 +45444 719 +A22A2 403 +6366Q 36 +35366 452 +293J3 576 +JKK3J 402 +425AT 338 +344J4 975 +7K7A8 490 +7QQ7Q 242 +T9T9K 542 +2JJT6 440 +76676 541 +AKA66 361 +7557Q 431 +5K552 511 +997K7 179 +79779 885 +85585 961 +TQQQ8 751 +9TAT6 504 +84248 654 +222JJ 865 +6AKK8 573 +AQ3T8 30 +77676 670 +T44J2 808 +J7J5Q 897 +44343 57 +TJ7T5 945 +JKTTK 60 +3333Q 894 +6886J 473 +8J7J3 990 +77797 915 +77J98 155 +KKQT8 736 +8A8AJ 219 +AQQJA 75 +75J58 349 +78978 898 +48TAA 726 +56A6A 45 +888JJ 170 +Q7KK3 294 +QQA7A 199 +A4653 193 +44545 602 +622K7 612 +T5TJ9 860 +8T888 548 +8TQJ4 410 +TQ578 446 +98988 367 +5989T 151 +QQ35J 679 +73677 416 +J33Q5 137 +6564J 913 +4847Q 807 +39292 874 +JQA45 810 +97975 943 +Q9839 296 +9599T 661 +J9699 723 +44J72 875 +T29A9 889 +QQ53K 1000 +88988 20 +QJQK5 769 +KAKKK 132 +7327J 177 +QQQAQ 704 +2KTK6 257 +474A4 928 +9A748 501 +5A535 469 +2T426 190 +53353 318 +Q7Q78 694 +92738 796 +25995 772 +QQQ22 877 +9K999 238 +JJQ5A 424 +4QA4J 7 +KQT2A 347 +27787 754 +823T5 159 +54347 702 +ATA55 166 +9Q8T7 887 +K8338 631 +945AJ 658 +TJTTJ 16 +7A478 313 +93998 2 +A5A93 342 +KKQQK 921 +3K242 52 +9AAJT 43 +TT33Q 337 +22452 139 +2AQK8 594 +6AQ58 503 +KJ5JQ 122 +9Q787 988 +7626T 228 +J99J9 377 +6J727 378 +45J33 216 +A555K 360 +6J62K 959 +Q7Q47 141 +95644 116 +5K755 56 +7A7QQ 773 +27K92 663 +A4A77 841 +763J4 872 +3493J 478 +42K9K 103 +43433 973 +K6A4K 38 +T257Q 307 +2KQKK 992 +TT553 627 +66664 508 +88A82 243 +QJQQQ 804 +2T99T 150 +2JQT3 245 +44644 786 +675TK 194 +45KKA 1 +JJJJJ 543 +T4TTT 530 +K6KK6 336 +TT8Q3 888 +T999Q 350 +36643 176 +95KKK 832 +J7386 375 +K8KK8 954 +82JK3 411 +AAAAT 571 +3677J 854 +9998J 604 +5JQT4 94 +JAKKQ 635 +TT986 15 +5855Q 756 +243Q8 127 +T69A3 821 +63A7T 902 +QQ8Q8 805 +AQAAK 371 +83J33 981 +AQ525 549 +72486 147 +36664 715 +QQTTQ 312 +686A9 920 +J63J7 486 +4AAAQ 451 +Q5452 84 +66688 191 +3QAQ9 285 +925K6 66 +824Q8 5 +JTQQT 806 +J5J33 344 +A2A35 428 +72943 262 +K9966 581 +66J69 991 +788J7 728 +AA7AA 471 +5555K 167 +J4A62 488 +JJ699 258 +36386 600 +A4AA4 405 +53Q9T 211 +3377A 985 +K7Q83 404 +J3TT7 265 +Q9QQQ 482 +82736 273 +92K4A 771 +68888 417 +A7AA7 625 +29333 630 +558QK 536 +7J9J7 247 +66T66 586 +AKA9A 11 +73J3J 67 +Q6226 570 +885J5 457 +7447J 869 +TA2A2 688 +J9685 254 +4JKK4 275 +8QQQ7 442 +82383 244 +43333 19 +573JT 701 +A666A 777 +999J9 984 +JJ444 822 +KJ3A4 505 +22494 387 +TJT77 301 +K2K2K 112 +88338 844 +5AA5A 388 +33J63 233 +9658Q 432 +797K7 291 +AJ3TT 935 +K2255 483 +66966 286 +33555 101 +AQ4QQ 944 +77K77 575 +4T4QQ 650 +32J6T 948 +AK32Q 666 +57455 685 +9823A 708 +8TTTK 474 +22575 102 +77577 368 +88J28 90 +A4343 610 +24826 82 +QQ8QQ 158 +99QQ9 892 +77468 99 +3T773 4 +4QQ3Q 620 +85437 212 +53655 745 +Q6664 156 +7447Q 320 +673K5 502 +4TJ7Q 917 +4TJ44 281 +53545 186 +TQ54A 957 +8J242 818 +4J75A 938 +95T8A 499 +KJ6KK 657 +T5TTT 12 +AAA4A 878 +6Q66K 788 +7TT22 450 +882QA 880 +5KT99 397 +3955T 263 +J68Q8 939 +6T395 742 +3KQ69 345 +Q9333 425 +J7777 695 +722Q7 130 +T7TT6 775 +TTT88 78 +AQQ22 815 +J8837 616 +223Q3 271 +4KKK4 28 +95999 879 +ATTT6 34 +4J4JA 603 +Q5972 37 +798K6 963 +29J4Q 217 +2AAA3 830 +99J9T 893 +5J2K2 235 +TTT55 937 +9587T 906 +4T3JK 968 +K88K8 734 +JT223 801 +9QJ2Q 418 +K8866 528 +887AA 487 +6733J 426 +82887 17 +54TQK 643 +44J94 639 +58K6A 470 +3TTTT 223 +T4TT4 760 +82435 942 +K494Q 114 +77792 556 +5J82J 118 +2T8AA 559 +9494A 706 +J4666 295 +33J7K 749 +8JQ88 717 +TJTTT 672 +4AAKK 557 +Q77QJ 629 +KKJK5 535 +492JT 834 +9QK74 876 +7QQQQ 308 +622J2 946 +J489Q 160 +A2A2A 647 +845T2 362 +Q7TT4 104 +T7KQA 513 +8T8T8 891 +25J82 6 +3333J 53 +J4544 443 +3377Q 551 +KKTQQ 655 +22822 59 +Q9Q9Q 278 +94JTK 363 +66699 206 +7A499 882 +T3663 677 +4K44Q 21 +82A42 197 +4824Q 566 +T8TT4 624 +KQJ7Q 951 +TJT89 163 +65A5A 884 +3T63A 92 +A3A34 434 +T7J88 202 +4K9A3 969 +52333 814 +J3977 615 +86666 697 +8A987 866 +5434K 464 +75888 974 +4444K 115 +62K32 143 +5J5TT 140 +T4QTQ 324 +K2282 314 +39993 518 +2AJ4J 83 +K96K9 952 +Q683J 851 +JJ4J8 724 +2222T 611 +7J676 595 +3T333 540 +88848 3 +2Q679 463 +J68J6 97 +AAA5A 276 +22272 288 +3353J 171 +KK67J 207 +34QJ7 617 +TTAKK 714 +AA6JA 529 +A8299 373 +5Q222 79 +666J6 953 +KQ29Q 799 +533TT 735 +JQAQQ 901 +995T3 716 +K2AK2 531 +7776Q 68 +94Q4Q 87 +AAA88 999 +T2434 149 +TQTQ7 385 +255T5 302 +99T99 449 +798TA 496 +7T6Q8 746 +Q2QKQ 873 +75776 300 +28588 303 +5KT5A 922 +KJT64 409 +AJAAA 924 +595JA 867 +44J93 27 +2K384 690 +JKKKK 744 +K57KQ 124 +T4464 109 +29AKJ 705 +8JK8K 261 +K6T3J 947 +T5588 125 +6A8K4 316 +35555 305 +63AAJ 560 +66J67 578 +KQ77K 646 +T654J 33 +38AKK 230 +AJ99A 838 +T6TTK 252 +6666K 689 +99A33 965 +88QAJ 764 +T9Q23 899 +8A22T 829 +478Q9 366 +TT2TT 971 +34T2A 259 +AAQAJ 23 +J4T52 776 +9999A 277 +68896 994 +55585 18 +88999 131 +77389 514 +75AQJ 787 +88Q88 51 +3J4JQ 678 +4J643 394 +6634J 757 +74496 249 +555J5 226 +T3TT4 881 +93739 157 +377K8 328 +JJ6J3 81 +8JA9K 720 +T3TT5 828 +33A33 106 +K6KKK 413 +86868 895 +6J3QQ 323 +4JQ93 192 +939J9 729 +7Q77Q 671 +Q2222 676 +8A83Q 823 +TTT3J 74 +94969 816 +5TK77 766 +QKA87 467 +JQ736 427 +JT374 870 +J949J 456 +8AT8A 299 +K9KK8 395 +932TA 669 +J3AAT 105 +474KK 441 +7J738 713 +742AT 793 +K387J 145 +4457A 264 +5T5J5 908 +99996 121 +AAJ4A 817 +J4JJJ 25 +99J59 63 +5TKKA 983 +J454K 396 +K222J 290 +99992 393 +A2JQQ 321 +58AAA 790 +39333 165 +4264T 737 +69969 327 +AQAQA 537 +KT9J8 49 +4QT86 126 +KKAJK 304 +84448 414 +Q2425 444 +6558A 675 +A9QAJ 770 +333QQ 607 +93983 73 +929T9 856 +JJAAA 352 +67TQT 382 +6579K 55 +TT7TT 544 +9AAK6 784 +65A82 855 +48KJ9 111 +388AK 272 +6T677 890 +2AA92 632 +663J3 623 +TTJQT 386 +49475 180 +4TKTT 461 +88333 722 +Q97T4 740 +7T624 315 +66K6K 86 +33398 826 +922J5 912 +93875 89 +KK3AK 447 +32T2T 383 +77KKJ 699 +9T5A7 622 +3J823 750 +8TKJ6 224 +3464T 730 +54555 138 +526J7 389 +A5794 497 +779JK 916 +T333T 545 +74253 743 +29222 227 +TKTJT 552 +9AJ89 574 +637J6 236 +KKQKK 868 +9QQJ4 683 +K42Q6 267 +9243Q 934 +8T98T 210 +T6K58 831 +29J99 29 +JQ4QT 353 +56QTQ 692 +335J9 825 +24J84 208 +A2924 859 +A8888 933 +577K2 148 +5AKKK 429 +23KK3 201 +29229 811 +44T4T 455 +9QT2J 755 +39QAT 172 +A2548 423 +AK692 270 +A44Q4 698 +A4443 510 +69527 415 +4T444 638 +AKJ36 927 +K355A 561 +32Q3Q 220 +22A22 93 +JTQTA 850 +2Q2Q2 188 +77787 135 +68T6T 813 +AAQA7 168 +T4554 967 +K6888 240 +2AA8A 642 +AA333 13 +8KTKK 70 +99K93 686 +89588 949 +K4565 372 +8T9K4 601 +33TJJ 763 +23J33 565 +KQK65 819 +K534J 721 +43385 563 +J5AA5 379 +88222 979 +5JTTJ 515 +2QQ8A 196 +8T756 849 +38288 454 +386QT 310 +Q5TT5 936 +4QQTQ 852 +QQ446 46 +QT6JQ 926 +242Q2 605 +44999 26 +93929 10 +A23A3 925 +66366 564 +88A8Q 809 +93222 356 +45AQ6 800 +QKKAK 359 +7A645 960 +J2KQQ 289 +KKK5K 203 +7QA44 485 +JQQ69 128 +Q2QT5 22 +K84KK 993 +J32A4 430 +999QK 778 +68Q3K 753 +4884J 221 +J44JJ 340 +JTT93 339 +63TT8 348 +4TTT6 725 +6KA2Q 335 +QTKKT 592 +4325K 229 +Q447Q 606 +78TTT 506 +66626 406 +27444 621 +27Q3Q 584 +28T27 964 +QTTTT 598 +8JJA8 649 +Q773K 847 +2AT8Q 231 +39574 241 +34QJ8 239 +J66KK 98 +54J3A 164 +77A87 582 +KJJKK 768 +J6892 846 +77TT7 911 +44834 184 +AJKJT 329 +TTTA4 596 +5453A 792 +5666J 493 +TA3A8 333 +7TA7A 585 +7JJ77 645 +K6KK7 843 +KKK9K 555 +33KT6 123 +5AA84 958 +93798 341 +555AA 783 +TAT33 266 +Q6QQ6 940 +7AJQ6 205 +A6656 572 +J8JJJ 660 +77477 861 +QJ666 173 +Q344J 955 +6699A 332 +529A9 976 +QK6KQ 640 +44QQQ 298 +J399K 9 +7J294 966 +9TAT7 613 +2K3Q7 680 +999Q5 532 +T899T 198 +Q95QK 42 +97947 509 +K777K 682 +K45K4 554 +82333 153 +2J7KK 802 +Q6999 187 +27732 41 +57865 628 +62226 47 +QQKA2 398 +77772 129 +67499 727 +3J8K8 752 +5J27A 833 +84444 741 +8KJKK 567 +AAJJK 904 +87768 780 +66766 534 +AA66A 989 +76868 32 +47TTT 512 +55J53 748 +49249 550 +2566K 812 +5775A 376 +J9K99 399 +9J66J 325 +36JQ6 364 +99979 909 +2A792 608 +J848K 326 +73374 533 +3J655 591 +Q6QQ4 580 +65656 845 +54477 626 +6299Q 225 +Q8768 707 +7989K 408 +7QQ73 525 +76Q2A 653 +A4A44 369 +23737 618 +49696 24 +52542 905 +22262 31 +K686K 346 +5TT8J 185 +76TJ6 494 +TQJ77 711 +33636 120 +4TA97 662 +43946 691 +77262 986 +7J7KJ 370 +TTK9Q 391 +T8387 498 +43J79 781 +66846 133 +2J222 765 +3KTQ3 222 +26KQJ 641 +T94KQ 857 +KKK7K 918 +4644Q 152 +77K6K 282 +A4444 664 +QQ8AA 644 +555JJ 997 +22727 824 +K3K2K 929 +9QK88 696 +44465 480 +K3JK3 110 +22242 718 +KKK9J 998 +QTQTT 462 +TTT6T 214 +5QQTQ 8 +KT593 789 +8QQ68 181 +QKK44 357 +JJQ7J 587 +8858J 522 +55559 351 +93995 673 +9AAT9 700 +78JQJ 739 +32323 950 +3338A 747 +J22TT 803 +T2893 475 +3T36T 292 +JQ5T2 759 +274Q4 142 +7737Q 579 +92T22 343 +Q2QQ8 100 +762J8 309 +A288A 322 +3569Q 932 +59455 972 +6J668 836 +29A84 562 +QQAQA 468 +8QJKA 76 +66JK5 85 +TTT28 634 +2K67T 146 +44A42 674 +K97KT 40 +55942 839 +JQ5QT 306 +22TTT 274 +Q3J6A 61 +65555 204 +9T9T9 260 +J6778 269 +7727J 466 +72T58 995 +3333K 910 +49292 108 +9A292 520 +T7TTK 527 +44888 209 +QT6Q3 848 +2JQ22 354 +73TT3 588 +6KT83 507 +AA8AA 519 +QK4QK 558 +9KA97 390 +6K2KK 526 +47KJ2 590 +666QQ 253 +4AQ8J 88 +AJA82 445 +68AAA 652 +6A42K 64 +K2225 237 +6544K 334 +3685A 178 +44324 797 +Q27K6 687 +TTT42 614 +99595 384 +74474 412 +J5745 293 +Q4444 864 diff --git a/src/day7.rs b/src/day7.rs new file mode 100644 index 0000000..ccf7e53 --- /dev/null +++ b/src/day7.rs @@ -0,0 +1,197 @@ + +#[derive(Debug, PartialEq, PartialOrd)] +enum Type { + HighCard, + OnePair, + TwoPairs, + ThreeOfAKind, + FullHouse, + FourOfAKind, + FiveOfAKind, +} + +#[derive(Debug)] +struct Game { + hand: Vec, + bid: usize, +} + +impl Game { + #[cfg(test)] + fn new(hand: &str, bid: usize) -> Self { + Game { hand: hand.chars().collect(), bid } + } + + fn classify(&self) -> Type { + // Count the number of occurrences of each card, and then check + // the number of occurrences of each number of occurrences. + let mut counts = [0; 13]; + for card in &self.hand { + match card { + 'A' => counts[12] += 1, + 'K' => counts[11] += 1, + 'Q' => counts[10] += 1, + 'J' => counts[9] += 1, + 'T' => counts[8] += 1, + _ => counts[card.to_digit(10).unwrap() as usize - 2] += 1, + } + } + let mut number_of_occurrences = [0; 6]; + for count in &counts { + number_of_occurrences[*count] += 1; + } + if number_of_occurrences[5] == 1 { + return Type::FiveOfAKind; + } + if number_of_occurrences[4] == 1 { + return Type::FourOfAKind; + } + if number_of_occurrences[3] == 1 && number_of_occurrences[2] == 1 { + return Type::FullHouse; + } + if number_of_occurrences[3] == 1 { + return Type::ThreeOfAKind; + } + if number_of_occurrences[2] == 2 { + return Type::TwoPairs; + } + if number_of_occurrences[2] == 1 { + return Type::OnePair; + } + Type::HighCard + } +} + +impl std::cmp::PartialEq for Game { + fn eq(&self, other: &Self) -> bool { + self.hand == other.hand + } +} + +impl std::cmp::PartialOrd for Game { + fn partial_cmp(&self, other: &Self) -> Option { + static CARD_ORDER: &str = "23456789TJQKA"; + + print!("comparing {:?} and {:?}: ", self, other); + // Compare the hand first by their classification + let self_hand = self.classify(); + let other_hand = other.classify(); + if self_hand != other_hand { + let result = self_hand.partial_cmp(&other_hand); + println!("different hand types ({:?} vs {:?}: {:?})", self_hand, other_hand, result); + return result; + } + // If that's still equal, compare the cards, in order. + for (self_card, other_card) in self.hand.iter().zip(other.hand.iter()) { + if self_card != other_card { + let result = CARD_ORDER.find(*self_card).partial_cmp(&CARD_ORDER.find(*other_card)); + println!("different cards ({} vs {}: {:?})", self_card, other_card, result); + return result; + } + } + + // If we get here, the hands are equal. + println!("equal"); + Some(std::cmp::Ordering::Equal) + } +} + +struct GameList { + games: Vec +} + +impl std::str::FromStr for GameList { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let mut games = Vec::new(); + for line in s.split('\n') { + if let Some((hand, bid)) = line.split_once(' ') { + let bid = bid.parse::().map_err(|_| "cannot parse bid")?; + let hand = hand.chars().collect::>(); + games.push(Game { hand, bid }); + } + } + Ok(GameList { games }) + } +} + +impl GameList { + fn winnings(&mut self) -> usize { + // Sort the games by their rank, and then calculate the winnings. + self.games.sort_by(|a, b| a.partial_cmp(b).unwrap()); + println!("games = {:?}", self.games); + + let mut result = 0; + for (rank, game) in self.games.iter().enumerate() { + result += (rank + 1) * game.bid; + } + result + } +} + +pub fn main() { + match std::fs::read_to_string("day7.input") { + Ok(input) => { + if let Ok(mut game_list) = input.parse::() { + println!("total winnings (part 1) = {}", game_list.winnings()); + } + }, + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn game_classify_tests() { + assert_eq!(Game::new("AAAAA", 0).classify(), Type::FiveOfAKind); + assert_eq!(Game::new("AA8AA", 0).classify(), Type::FourOfAKind); + assert_eq!(Game::new("23332", 0).classify(), Type::FullHouse); + assert_eq!(Game::new("TTT98", 0).classify(), Type::ThreeOfAKind); + assert_eq!(Game::new("23432", 0).classify(), Type::TwoPairs); + assert_eq!(Game::new("A23A4", 0).classify(), Type::OnePair); + assert_eq!(Game::new("23456", 0).classify(), Type::HighCard); + } + + #[test] + fn game_partial_ord_tests() { + // So, 33332 and 2AAAA are both four of a kind hands, but 33332 is stronger because its first card is stronger. + assert!(Game::new("33332", 0) > Game::new("2AAAA", 0)); + // Similarly, 77888 and 77788 are both a full house, but 77888 is stronger because its third card is stronger (and both hands have the same first and second card). + assert!(Game::new("77888", 0) > Game::new("77788", 0)); + + // From failed attempts: + assert!(Game::new("22272", 0) > Game::new("22262", 0)); + assert!(Game::new("22262", 0) < Game::new("22272", 0)); + } + + #[test] + fn game_list_ordering_tests() { + let mut game_list = GameList { games: vec![ + Game::new("JJJJJ", 0), + Game::new("2222T", 0), + Game::new("22272", 0), + Game::new("22262", 0), + ]}; + game_list.winnings(); + assert_eq!(game_list.games, vec![ + Game::new("2222T", 0), + Game::new("22262", 0), + Game::new("22272", 0), + Game::new("JJJJJ", 0), + ]); + } + + #[test] + fn part1_example() { + static DATA: &str = "32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483"; + assert_eq!(DATA.parse::().ok().unwrap().winnings(), 6440); + } +} diff --git a/src/main.rs b/src/main.rs index 9f659f8..0889929 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day6; +mod day7; fn main() { - day6::main() + day7::main() } From bc0125dfc896b0d4b1837d28a5ece8be6ddbc302 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Fri, 8 Dec 2023 21:40:25 +0100 Subject: [PATCH 079/120] Blindly adding jokers: Not good enough. --- src/day7.rs | 198 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 147 insertions(+), 51 deletions(-) diff --git a/src/day7.rs b/src/day7.rs index ccf7e53..15d90ce 100644 --- a/src/day7.rs +++ b/src/day7.rs @@ -21,12 +21,55 @@ impl Game { fn new(hand: &str, bid: usize) -> Self { Game { hand: hand.chars().collect(), bid } } +} + +impl std::cmp::PartialEq for Game { + fn eq(&self, other: &Self) -> bool { + self.hand == other.hand + } +} + +trait GameRules { + fn card_order(&self) -> &str; + fn classify(&self, hand: &[char]) -> Type; + + fn cmp_game(&self, a: &Game, b: &Game) -> Option { + print!("comparing {:?} and {:?}: ", a, b); + // Compare the hand first by their classification + let a_hand = self.classify(&a.hand); + let b_hand = self.classify(&b.hand); + if a_hand != b_hand { + let result = a_hand.partial_cmp(&b_hand); + println!("different hand types ({:?} vs {:?}: {:?})", a_hand, b_hand, result); + return result; + } + // If that's still equal, compare the cards, in order. + for (a_card, b_card) in a.hand.iter().zip(b.hand.iter()) { + if a_card != b_card { + let result = self.card_order().find(*a_card).partial_cmp(&self.card_order().find(*b_card)); + println!("different cards ({} vs {}: {:?})", a_card, b_card, result); + return result; + } + } + + // If we get here, the hands are equal. + println!("equal"); + Some(std::cmp::Ordering::Equal) + } +} + +struct NoJokerRules {} - fn classify(&self) -> Type { +impl GameRules for NoJokerRules { + fn card_order(&self) -> &str { + "23456789TJQKA" + } + + fn classify(&self, hand: &[char]) -> Type { // Count the number of occurrences of each card, and then check // the number of occurrences of each number of occurrences. let mut counts = [0; 13]; - for card in &self.hand { + for card in hand { match card { 'A' => counts[12] += 1, 'K' => counts[11] += 1, @@ -62,37 +105,64 @@ impl Game { } } -impl std::cmp::PartialEq for Game { - fn eq(&self, other: &Self) -> bool { - self.hand == other.hand - } -} +struct JokerRules {} -impl std::cmp::PartialOrd for Game { - fn partial_cmp(&self, other: &Self) -> Option { - static CARD_ORDER: &str = "23456789TJQKA"; +impl GameRules for JokerRules { + fn card_order(&self) -> &str { + "J23456789TQKA" + } - print!("comparing {:?} and {:?}: ", self, other); - // Compare the hand first by their classification - let self_hand = self.classify(); - let other_hand = other.classify(); - if self_hand != other_hand { - let result = self_hand.partial_cmp(&other_hand); - println!("different hand types ({:?} vs {:?}: {:?})", self_hand, other_hand, result); - return result; + fn classify(&self, hand: &[char]) -> Type { + // Count the number of occurrences of each card, and then check + // the number of occurrences of each number of occurrences. + let mut counts = [0; 13]; + for card in hand { + match card { + 'A' => counts[12] += 1, + 'K' => counts[11] += 1, + 'Q' => counts[10] += 1, + 'J' => counts[9] += 1, + 'T' => counts[8] += 1, + _ => counts[card.to_digit(10).unwrap() as usize - 2] += 1, + } } - // If that's still equal, compare the cards, in order. - for (self_card, other_card) in self.hand.iter().zip(other.hand.iter()) { - if self_card != other_card { - let result = CARD_ORDER.find(*self_card).partial_cmp(&CARD_ORDER.find(*other_card)); - println!("different cards ({} vs {}: {:?})", self_card, other_card, result); - return result; + + // The jokers can be used to replace any card, so we can just add them + // to the counts as long as we don't use too many of them. + let joker_count = counts[9]; + print!("joker_count = {}, counts = {:?}", joker_count, counts); + for (i, count) in counts.iter_mut().enumerate() { + if i != 9 { + *count += joker_count; } } + println!(" -> {:?}", counts); - // If we get here, the hands are equal. - println!("equal"); - Some(std::cmp::Ordering::Equal) + let mut number_of_occurrences = [0; 6]; + for count in &counts { + number_of_occurrences[*count] += 1; + } + println!("number_of_occurrences = {:?}", number_of_occurrences); + + if number_of_occurrences[5] == 1 { + return Type::FiveOfAKind; + } + if number_of_occurrences[4] == 1 { + return Type::FourOfAKind; + } + if number_of_occurrences[3] == 1 && number_of_occurrences[2] == 1 { + return Type::FullHouse; + } + if number_of_occurrences[3] == 1 { + return Type::ThreeOfAKind; + } + if number_of_occurrences[2] == 2 { + return Type::TwoPairs; + } + if number_of_occurrences[2] == 1 { + return Type::OnePair; + } + Type::HighCard } } @@ -117,9 +187,9 @@ impl std::str::FromStr for GameList { } impl GameList { - fn winnings(&mut self) -> usize { + fn winnings(&mut self, rules: &dyn GameRules) -> usize { // Sort the games by their rank, and then calculate the winnings. - self.games.sort_by(|a, b| a.partial_cmp(b).unwrap()); + self.games.sort_by(|a, b| rules.cmp_game(a, b).unwrap()); println!("games = {:?}", self.games); let mut result = 0; @@ -134,7 +204,8 @@ pub fn main() { match std::fs::read_to_string("day7.input") { Ok(input) => { if let Ok(mut game_list) = input.parse::() { - println!("total winnings (part 1) = {}", game_list.winnings()); + println!("total winnings (no jokers) = {}", game_list.winnings(&NoJokerRules {})); + println!("total winnings (jokers) = {}", game_list.winnings(&JokerRules {})); } }, Err(reason) => println!("error = {}", reason) @@ -145,38 +216,47 @@ pub fn main() { mod tests { use super::*; + static DATA: &str = "32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483"; + #[test] - fn game_classify_tests() { - assert_eq!(Game::new("AAAAA", 0).classify(), Type::FiveOfAKind); - assert_eq!(Game::new("AA8AA", 0).classify(), Type::FourOfAKind); - assert_eq!(Game::new("23332", 0).classify(), Type::FullHouse); - assert_eq!(Game::new("TTT98", 0).classify(), Type::ThreeOfAKind); - assert_eq!(Game::new("23432", 0).classify(), Type::TwoPairs); - assert_eq!(Game::new("A23A4", 0).classify(), Type::OnePair); - assert_eq!(Game::new("23456", 0).classify(), Type::HighCard); + fn no_joker_rules_classify() { + let rules = NoJokerRules {}; + assert_eq!(rules.classify(&"AAAAA".chars().collect::>()), Type::FiveOfAKind); + assert_eq!(rules.classify(&"AA8AA".chars().collect::>()), Type::FourOfAKind); + assert_eq!(rules.classify(&"23332".chars().collect::>()), Type::FullHouse); + assert_eq!(rules.classify(&"TTT98".chars().collect::>()), Type::ThreeOfAKind); + assert_eq!(rules.classify(&"23432".chars().collect::>()), Type::TwoPairs); + assert_eq!(rules.classify(&"A23A4".chars().collect::>()), Type::OnePair); + assert_eq!(rules.classify(&"23456".chars().collect::>()), Type::HighCard); } #[test] - fn game_partial_ord_tests() { + fn no_joker_rules_cmp_game() { + let rules = NoJokerRules {}; + // So, 33332 and 2AAAA are both four of a kind hands, but 33332 is stronger because its first card is stronger. - assert!(Game::new("33332", 0) > Game::new("2AAAA", 0)); + assert!(rules.cmp_game(&Game::new("33332", 0), &Game::new("2AAAA", 0)).unwrap() == std::cmp::Ordering::Greater); // Similarly, 77888 and 77788 are both a full house, but 77888 is stronger because its third card is stronger (and both hands have the same first and second card). - assert!(Game::new("77888", 0) > Game::new("77788", 0)); + assert!(rules.cmp_game(&Game::new("77888", 0), &Game::new("77788", 0)).unwrap() == std::cmp::Ordering::Greater); // From failed attempts: - assert!(Game::new("22272", 0) > Game::new("22262", 0)); - assert!(Game::new("22262", 0) < Game::new("22272", 0)); + assert!(rules.cmp_game(&Game::new("22272", 0), &Game::new("22262", 0)).unwrap() == std::cmp::Ordering::Greater); + assert!(rules.cmp_game(&Game::new("22262", 0), &Game::new("22272", 0)).unwrap() == std::cmp::Ordering::Less); } #[test] - fn game_list_ordering_tests() { + fn no_joker_rules_game_ordering() { let mut game_list = GameList { games: vec![ Game::new("JJJJJ", 0), Game::new("2222T", 0), Game::new("22272", 0), Game::new("22262", 0), ]}; - game_list.winnings(); + game_list.winnings(&NoJokerRules {}); assert_eq!(game_list.games, vec![ Game::new("2222T", 0), Game::new("22262", 0), @@ -187,11 +267,27 @@ mod tests { #[test] fn part1_example() { - static DATA: &str = "32T3K 765 -T55J5 684 -KK677 28 -KTJJT 220 -QQQJA 483"; - assert_eq!(DATA.parse::().ok().unwrap().winnings(), 6440); + assert_eq!(DATA.parse::().ok().unwrap().winnings(&NoJokerRules {}), 6440); + } + + #[test] + fn joker_rules_classify() { + let rules = JokerRules {}; + assert_eq!(rules.classify(&"QJJQ2".chars().collect::>()), Type::FourOfAKind); + assert_eq!(rules.classify(&"KTJJT".chars().collect::>()), Type::FourOfAKind); + assert_eq!(rules.classify(&"T55J5".chars().collect::>()), Type::FourOfAKind); + } + + #[test] + fn joker_rules_cmp_game() { + let rules = JokerRules {}; + + // JKKK2 is weaker than QQQQ2 because J is weaker than Q. + assert!(rules.cmp_game(&Game::new("JKKK2", 0), &Game::new("QQQQ2", 0)).unwrap() == std::cmp::Ordering::Less); + } + + #[test] + fn part2_example() { + assert_eq!(DATA.parse::().ok().unwrap().winnings(&JokerRules {}), 5905); } } From 3d68019795ef71318c64773f0c7ebeb807dcee77 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 9 Dec 2023 11:51:58 +0100 Subject: [PATCH 080/120] Day 7, part 2: Proper joker rules. There are likely smarter ways to do this, but simply writing out the combinations works quite nicely. As usual: Unit testing is good, in this case also helpful: List out the classifications of all games with jokers, and verify them by hand. --- day7-jokers.input | 299 ++++++++++++++++++++++++++++++++++++++++++++++ src/day7.rs | 68 ++++++++--- 2 files changed, 348 insertions(+), 19 deletions(-) create mode 100644 day7-jokers.input diff --git a/day7-jokers.input b/day7-jokers.input new file mode 100644 index 0000000..2e01d90 --- /dev/null +++ b/day7-jokers.input @@ -0,0 +1,299 @@ +AATKJ +7227J +TJ2J9 +4432J +J9Q77 +7QQJQ +J9893 +8J222 +J5222 +J65A9 +K997J +8888J +3KK4J +QQJ59 +22J33 +5KJ45 +2TJKA +TJ6K6 +4J888 +3KKKJ +6467J +46J5J +7JT55 +J3282 +JJ8QQ +2JT22 +QQQJJ +2JK45 +2QJ32 +5KJK9 +5T7J8 +2244J +AAJ5Q +KK2J3 +6QQJ6 +J4444 +QAJ22 +KT5J5 +7K3J9 +JK7A4 +4345J +27J2Q +333J9 +6TJ66 +74JK9 +4424J +44AJA +A6A6J +9J9JJ +669J7 +Q25JK +JJ2K8 +293J3 +JKK3J +344J4 +2JJT6 +222JJ +T44J2 +J7J5Q +TJ7T5 +JKTTK +6886J +8J7J3 +77J98 +8A8AJ +AQQJA +75J58 +888JJ +T5TJ9 +8TQJ4 +QQ35J +J33Q5 +6564J +JQA45 +J9699 +44J72 +QJQK5 +7327J +JJQ5A +4QA4J +945AJ +TJTTJ +9AAJT +KJ5JQ +J99J9 +6J727 +45J33 +6J62K +763J4 +3493J +QJQQQ +2JQT3 +JJJJJ +J7386 +82JK3 +3677J +9998J +5JQT4 +JAKKQ +83J33 +J63J7 +JTQQT +J5J33 +66J69 +788J7 +J4A62 +JJ699 +J3TT7 +7J9J7 +73J3J +885J5 +7447J +J9685 +4JKK4 +573JT +999J9 +JJ444 +KJ3A4 +TJT77 +33J63 +AJ3TT +32J6T +88J28 +4TJ7Q +4TJ44 +8J242 +4J75A +KJ6KK +J68Q8 +J7777 +J8837 +4J4JA +29J4Q +99J9T +5J2K2 +4T3JK +JT223 +9QJ2Q +6733J +44J94 +5J82J +J4666 +33J7K +8JQ88 +TJTTT +Q77QJ +KKJK5 +492JT +622J2 +J489Q +25J82 +3333J +J4544 +94JTK +KQJ7Q +TJT89 +T7J88 +J3977 +5J5TT +2AJ4J +Q683J +JJ4J8 +7J676 +J68J6 +3353J +KK67J +34QJ7 +AA6JA +666J6 +JQAQQ +KJT64 +AJAAA +595JA +44J93 +JKKKK +29AKJ +8JK8K +K6T3J +63AAJ +66J67 +T654J +AJ99A +88QAJ +AAQAJ +J4T52 +75AQJ +3J4JQ +4J643 +6634J +555J5 +JJ6J3 +8JA9K +6J3QQ +4JQ93 +939J9 +TTT3J +JQ736 +JT374 +J949J +J3AAT +7J738 +K387J +5T5J5 +AAJ4A +J4JJJ +99J59 +J454K +K222J +A2JQQ +KT9J8 +KKAJK +A9QAJ +JJAAA +48KJ9 +663J3 +TTJQT +922J5 +77KKJ +3J823 +8TKJ6 +526J7 +779JK +TKTJT +9AJ89 +637J6 +9QQJ4 +29J99 +JQ4QT +335J9 +24J84 +9QT2J +AKJ36 +JTQTA +33TJJ +23J33 +K534J +J5AA5 +5JTTJ +QT6JQ +J2KQQ +JQQ69 +J32A4 +4884J +J44JJ +JTT93 +8JJA8 +34QJ8 +J66KK +54J3A +KJJKK +J6892 +AJKJT +5666J +7JJ77 +7AJQ6 +J8JJJ +QJ666 +Q344J +J399K +7J294 +2J7KK +3J8K8 +5J27A +8KJKK +AAJJK +55J53 +J9K99 +9J66J +36JQ6 +J848K +3J655 +5TT8J +76TJ6 +TQJ77 +7J7KJ +43J79 +2J222 +26KQJ +555JJ +K3JK3 +KKK9J +JJQ7J +8858J +78JQJ +J22TT +JQ5T2 +762J8 +6J668 +8QJKA +66JK5 +JQ5QT +Q3J6A +J6778 +7727J +2JQ22 +47KJ2 +4AQ8J +AJA82 +J5745 diff --git a/src/day7.rs b/src/day7.rs index 15d90ce..b1a2495 100644 --- a/src/day7.rs +++ b/src/day7.rs @@ -116,50 +116,44 @@ impl GameRules for JokerRules { // Count the number of occurrences of each card, and then check // the number of occurrences of each number of occurrences. let mut counts = [0; 13]; + let mut joker_count = 0; for card in hand { match card { 'A' => counts[12] += 1, 'K' => counts[11] += 1, 'Q' => counts[10] += 1, - 'J' => counts[9] += 1, + 'J' => joker_count += 1, 'T' => counts[8] += 1, _ => counts[card.to_digit(10).unwrap() as usize - 2] += 1, } } - - // The jokers can be used to replace any card, so we can just add them - // to the counts as long as we don't use too many of them. - let joker_count = counts[9]; - print!("joker_count = {}, counts = {:?}", joker_count, counts); - for (i, count) in counts.iter_mut().enumerate() { - if i != 9 { - *count += joker_count; - } - } - println!(" -> {:?}", counts); + // println!("joker_count = {}, counts = {:?}", joker_count, counts); let mut number_of_occurrences = [0; 6]; for count in &counts { number_of_occurrences[*count] += 1; } - println!("number_of_occurrences = {:?}", number_of_occurrences); + // println!("number_of_occurrences = {:?}", number_of_occurrences); - if number_of_occurrences[5] == 1 { + // Account for the jokers: Note that some cases are "theoretical" only, for instance + // with 4 jokers you certainly have 4 of a kind, but you also have one other card and so end up + // with 5 of a kind instead. + if number_of_occurrences[5] == 1 || (number_of_occurrences[4] == 1 && joker_count == 1) || (number_of_occurrences[3] == 1 && joker_count == 2) || (number_of_occurrences[2] == 1 && joker_count == 3) || joker_count == 4 || joker_count == 5 { return Type::FiveOfAKind; } - if number_of_occurrences[4] == 1 { + if number_of_occurrences[4] == 1 || (number_of_occurrences[3] == 1 && joker_count == 1) || (number_of_occurrences[2] == 1 && joker_count == 2) || joker_count == 3 || joker_count == 4 { return Type::FourOfAKind; } - if number_of_occurrences[3] == 1 && number_of_occurrences[2] == 1 { + if (number_of_occurrences[3] == 1 && number_of_occurrences[2] == 1) || (number_of_occurrences[2] == 2 && joker_count == 1) || (number_of_occurrences[2] == 1 && joker_count == 2) || joker_count == 3 { return Type::FullHouse; } - if number_of_occurrences[3] == 1 { + if number_of_occurrences[3] == 1 || (number_of_occurrences[2] >= 1 && joker_count == 1) || joker_count == 2 || joker_count == 3 { return Type::ThreeOfAKind; } - if number_of_occurrences[2] == 2 { + if number_of_occurrences[2] == 2 || (number_of_occurrences[2] == 1 && joker_count == 1) { return Type::TwoPairs; } - if number_of_occurrences[2] == 1 { + if number_of_occurrences[2] == 1 || joker_count == 1 || joker_count == 2 { return Type::OnePair; } Type::HighCard @@ -276,6 +270,11 @@ QQQJA 483"; assert_eq!(rules.classify(&"QJJQ2".chars().collect::>()), Type::FourOfAKind); assert_eq!(rules.classify(&"KTJJT".chars().collect::>()), Type::FourOfAKind); assert_eq!(rules.classify(&"T55J5".chars().collect::>()), Type::FourOfAKind); + + assert_eq!(rules.classify(&"22J33".chars().collect::>()), Type::FullHouse); + assert_eq!(rules.classify(&"26KQJ".chars().collect::>()), Type::OnePair); + // This could make two pairs, but it makes a three-of-kind instead as that is higher in rank. + assert_eq!(rules.classify(&"223JA".chars().collect::>()), Type::ThreeOfAKind); } #[test] @@ -286,6 +285,37 @@ QQQJA 483"; assert!(rules.cmp_game(&Game::new("JKKK2", 0), &Game::new("QQQQ2", 0)).unwrap() == std::cmp::Ordering::Less); } + #[test] + fn joker_rules_game_ordering() { + let mut game_list = GameList { games: vec![ + Game::new("32T3K", 0), + Game::new("T55J5", 0), + Game::new("KK677", 0), + Game::new("KTJJT", 0), + Game::new("QQQJA", 0), + ]}; + game_list.winnings(&JokerRules {}); + assert_eq!(game_list.games, vec![ + Game::new("32T3K", 0), + Game::new("KK677", 0), + Game::new("T55J5", 0), + Game::new("QQQJA", 0), + Game::new("KTJJT", 0), + ]); + } + + #[test] + fn part2_jokers_classify() { + match std::fs::read_to_string("day7-jokers.input") { + Ok(input) => { + for hand in input.split_ascii_whitespace() { + println!("{} = {:?}", hand, JokerRules {}.classify(&hand.chars().collect::>())); + } + }, + Err(reason) => println!("error = {}", reason) + } + } + #[test] fn part2_example() { assert_eq!(DATA.parse::().ok().unwrap().winnings(&JokerRules {}), 5905); From 08456ce4b2ded706ff37af7f1e6a4eb90793ca94 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 9 Dec 2023 12:28:24 +0100 Subject: [PATCH 081/120] Simplify a bit --- src/day6.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/day6.rs b/src/day6.rs index 3df23a1..603dfe4 100644 --- a/src/day6.rs +++ b/src/day6.rs @@ -7,8 +7,8 @@ impl std::str::FromStr for RaceTable { fn from_str(s: &str) -> Result { if let Some((times_line, distances_line)) = s.split_once('\n') { - let times = times_line.split_ascii_whitespace().skip(1).map(|s| s.parse::()).collect::, _>>().map_err(|_| "cannot parse times")?; - let distances = distances_line.split_ascii_whitespace().skip(1).map(|s| s.parse::()).collect::, _>>().map_err(|_| "cannot parse distances")?; + let times = times_line.split_ascii_whitespace().skip(1).map(usize::from_str).collect::, _>>().map_err(|_| "cannot parse times")?; + let distances = distances_line.split_ascii_whitespace().skip(1).map(usize::from_str).collect::, _>>().map_err(|_| "cannot parse distances")?; if times.len() != distances.len() { return Err("mismatch between times and distances") } From b2b7bb62265e2823c38e82928c8912ed2200d7f0 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 9 Dec 2023 12:28:49 +0100 Subject: [PATCH 082/120] Day 9, part 1: Scarily simple ... --- day9.input | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/day9.rs | 79 +++++++++++++++++++++ src/main.rs | 4 +- 3 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 day9.input create mode 100644 src/day9.rs diff --git a/day9.input b/day9.input new file mode 100644 index 0000000..61ad55e --- /dev/null +++ b/day9.input @@ -0,0 +1,200 @@ +0 14 45 109 238 493 989 1942 3763 7260 14077 27610 54805 109473 218063 429227 829002 1564034 2875989 5151147 8990168 +15 18 30 59 111 187 296 499 999 2292 5394 12159 25703 50949 95308 169511 288607 473142 750534 1156659 1737663 +5 11 15 33 90 214 428 752 1253 2229 4693 11450 29258 72870 172222 384737 815757 1651623 3212059 6031479 10982866 +11 16 23 24 13 -7 -3 134 674 2194 5828 13721 29926 62289 126510 254929 515555 1053450 2181099 4575420 9702689 +16 31 60 112 215 439 934 1988 4110 8143 15412 27912 48541 81383 132046 208060 319340 478719 702556 1011424 1430883 +12 7 12 54 178 448 938 1712 2791 4113 5527 6958 9104 15500 37718 107235 300798 792410 1957506 4580209 10266638 +17 21 30 48 77 119 191 374 932 2554 6791 16781 38378 81826 164146 312433 568291 993667 1678380 2749678 4384195 +24 37 63 112 194 319 497 738 1052 1449 1939 2532 3238 4067 5029 6134 7392 8813 10407 12184 14154 +11 8 18 52 130 304 693 1530 3221 6416 12092 21648 37012 60760 96247 147750 220623 321464 458294 640748 880278 +22 33 42 54 85 172 386 856 1822 3745 7512 14784 28545 53920 99340 178142 310702 527209 871198 1403970 2210037 +18 20 24 34 54 88 140 214 314 444 608 810 1054 1344 1684 2078 2530 3044 3624 4274 4998 +-8 -10 1 46 151 357 744 1469 2818 5272 9587 16888 28777 47455 75858 117807 178172 263050 379957 538034 748267 +1 6 26 72 171 381 806 1611 3037 5416 9186 14906 23271 35127 51486 73541 102681 140506 188842 249756 325571 +5 20 41 68 101 140 185 236 293 356 425 500 581 668 761 860 965 1076 1193 1316 1445 +20 38 72 140 277 545 1041 1903 3314 5504 8750 13374 19739 28243 39311 53385 70912 92330 118052 148448 183825 +4 7 21 74 220 564 1301 2769 5512 10346 18439 31487 52233 85884 143500 249291 455277 869701 1711690 3417800 6854447 +0 1 9 36 101 231 473 938 1906 4032 8710 18677 38984 78578 153085 290356 542855 1017057 1944000 3845866 7918498 +12 15 30 67 130 208 262 208 -104 -915 -2586 -5631 -10754 -18890 -31250 -49370 -75164 -110981 -159666 -224625 -309894 +2 18 45 83 132 192 263 345 438 542 657 783 920 1068 1227 1397 1578 1770 1973 2187 2412 +10 11 20 47 100 195 375 731 1422 2715 5135 9968 20651 46080 107649 252985 580950 1284615 2721626 5524697 10768850 +-4 -4 9 49 141 337 751 1623 3426 7039 14036 27210 51589 96428 178991 331412 612714 1129686 2074056 3792092 6922209 +5 12 40 97 192 356 683 1398 2974 6351 13364 27575 55854 111344 219060 426682 825747 1593398 3073408 5928841 11418708 +18 36 65 116 222 456 965 2037 4241 8715 17723 35658 70733 137675 261817 485069 874340 1533078 2616693 4352728 7066744 +3 14 33 56 81 125 268 732 2005 5030 11514 24508 49620 97614 189795 368602 717489 1397080 2710069 5218030 9953981 +26 50 97 182 323 552 935 1601 2780 4850 8393 14260 23645 38168 59967 91799 137150 200354 286721 402674 555895 +14 29 73 160 309 548 930 1575 2752 5015 9407 17746 33007 59814 105056 178641 294402 471169 734021 1115732 1658425 +2 2 6 31 105 278 643 1364 2702 5023 8781 14539 23309 38000 67770 138871 318530 762996 1807680 4127011 9005033 +19 20 30 70 181 451 1057 2322 4787 9298 17108 29994 50389 81529 127615 193990 287331 415856 589546 820382 1122597 +17 32 74 157 295 502 792 1179 1677 2300 3062 3977 5059 6322 7780 9447 11337 13464 15842 18485 21407 +3 4 4 4 17 74 232 595 1362 2914 5950 11697 22294 41677 77846 148591 295156 612955 1317215 2877781 6287522 +19 37 64 98 137 179 222 264 303 337 364 382 389 383 362 324 267 189 88 -38 -191 +7 7 26 85 209 438 867 1734 3593 7652 16437 35081 73762 152177 307542 608680 1180815 2249821 4223028 7840205 14459843 +-5 -12 -20 -22 7 125 448 1196 2772 5887 11745 22303 40622 71326 121187 199855 320753 502158 768490 1151832 1693705 +5 0 -5 -10 -15 -20 -25 -30 -35 -40 -45 -50 -55 -60 -65 -70 -75 -80 -85 -90 -95 +-1 6 15 19 10 -3 49 371 1430 4169 10381 23363 49033 97772 187349 347401 626073 1099576 1885595 3161675 5189932 +13 26 42 57 64 60 53 70 173 497 1331 3267 7438 15847 31746 59946 106813 179516 283824 419381 570900 +18 44 94 176 298 479 782 1395 2798 6078 13503 29553 62744 128783 255871 493340 925282 1691416 3018156 5263702 8981990 +13 21 39 94 224 472 881 1507 2474 4102 7152 13269 25811 51524 104128 212091 435133 898089 1858087 3834270 7853652 +10 32 59 91 127 171 250 451 1002 2450 6028 14373 32912 72576 155200 324266 665886 1348552 2695773 5313987 10309945 +-2 -3 3 29 105 287 676 1453 2930 5610 10241 17840 29653 47006 70990 101910 138414 176203 206207 212095 166969 +4 8 24 56 111 199 340 598 1178 2648 6392 15474 36213 80955 172804 353468 695920 1324304 2444472 4389764 7688187 +-1 2 18 74 224 576 1339 2894 5893 11396 21068 37479 64607 108829 181221 303325 521487 940762 1800302 3631184 7569222 +11 21 41 68 95 115 131 179 376 1010 2694 6611 14882 31094 61030 113648 202361 346675 574247 923430 1446377 +0 -5 1 40 155 426 998 2125 4240 8071 14842 26641 47129 82940 146427 260898 470224 855763 1565015 2858398 5183119 +18 20 20 18 14 8 0 -10 -22 -36 -52 -70 -90 -112 -136 -162 -190 -220 -252 -286 -322 +16 37 63 102 179 355 759 1633 3390 6685 12499 22236 37833 61883 97771 149823 223468 325413 463831 648562 891327 +15 19 29 66 169 406 900 1878 3759 7322 14062 26987 52376 103452 207559 419283 843056 1670365 3239758 6135514 11361164 +4 9 29 79 179 352 622 1017 1588 2461 3945 6725 12175 22832 43078 80083 145068 254953 434461 718755 1156691 +3 10 14 26 78 235 623 1487 3295 6912 13896 27036 51386 96281 179189 332801 617539 1142726 2101074 3822974 6859390 +22 50 96 165 259 378 539 822 1446 2885 6082 12949 27610 59338 129001 282330 615951 1326821 2804217 5798898 11732018 +4 12 36 85 179 375 813 1797 3930 8328 16953 33136 62415 113897 202474 352388 602856 1016740 1693586 2788767 4540955 +5 9 14 20 37 99 281 722 1668 3566 7263 14399 28147 54587 105307 202555 390030 756604 1490039 2999763 6195548 +16 38 84 163 284 456 688 989 1368 1834 2396 3063 3844 4748 5784 6961 8288 9774 11428 13259 15276 +2 4 9 21 50 113 237 464 858 1514 2569 4215 6714 10415 15773 23370 33938 48384 67817 93577 127266 +6 11 24 56 127 269 546 1106 2280 4743 9752 19476 37433 69049 122354 208830 344426 550755 856488 1298960 1926003 +23 48 97 192 367 665 1144 1921 3296 6018 11796 24254 50761 106109 220203 454376 935673 1927092 3966811 8134512 16543215 +3 3 2 2 10 51 204 683 2012 5398 13507 32018 72611 158539 334894 687689 1380199 2724154 5322133 10354528 20154880 +19 22 29 53 130 339 824 1822 3703 7028 12638 21811 36577 60387 99564 166539 287349 519488 994437 2016603 4284750 +6 22 50 105 212 416 803 1539 2939 5583 10501 19454 35343 62783 108884 184286 304500 491612 776412 1201015 1822046 +-4 10 45 122 282 596 1173 2161 3736 6074 9301 13416 18182 22980 26621 27111 21364 4858 -28771 -88202 -184974 +24 45 84 149 257 449 814 1529 2922 5565 10404 18933 33419 57185 94958 153289 241052 370029 555588 817461 1180629 +8 25 68 164 354 705 1335 2454 4442 8017 14593 26988 50703 96031 181252 337183 613701 1090570 1900670 3289782 5776671 +6 8 24 79 221 533 1151 2292 4296 7686 13250 22149 36055 57323 89201 136082 203802 299988 434460 619691 871329 +12 39 95 203 399 739 1323 2356 4271 7943 15026 28447 53092 96719 171132 293648 488886 790903 1245697 1914091 2875005 +21 34 47 60 73 86 99 112 125 138 151 164 177 190 203 216 229 242 255 268 281 +-2 -9 -12 -7 15 78 246 672 1687 3973 8918 19345 40989 85484 176451 361958 739808 1507779 3060484 6169849 12309863 +30 51 83 136 220 342 515 803 1438 3055 7099 16464 36428 75950 149395 278751 496398 848483 1398947 2234240 3468748 +12 19 40 103 262 613 1312 2603 4872 8752 15318 26434 45350 77700 133126 227852 388660 658881 1107212 1840409 3021190 +17 30 49 86 182 432 1032 2374 5238 11174 23249 47476 95474 189272 369723 710808 1343267 2492574 4538333 8104714 14194474 +-6 -2 20 78 202 434 823 1415 2238 3282 4474 5648 6510 6598 5237 1489 -5902 -18570 -38592 -68558 -111646 +-1 2 7 14 23 34 47 62 79 98 119 142 167 194 223 254 287 322 359 398 439 +2 13 45 115 251 505 972 1824 3380 6256 11693 22272 43437 86660 175927 360989 744448 1536918 3168045 6505602 13277061 +2 6 8 8 12 35 111 320 842 2048 4638 9836 19652 37221 67229 116436 194306 313754 492020 751680 1121804 +8 19 32 50 97 235 600 1487 3542 8162 18272 39770 84180 173596 350194 695154 1367144 2681061 5267792 10392438 20572991 +7 18 43 101 223 458 894 1718 3351 6715 13723 28140 57076 113623 221703 425347 806851 1522272 2869567 5415767 10226825 +9 4 -1 -6 -11 -16 -21 -26 -31 -36 -41 -46 -51 -56 -61 -66 -71 -76 -81 -86 -91 +21 35 67 134 263 502 940 1751 3298 6359 12578 25337 51479 104872 214045 438707 905097 1880089 3923095 8191130 17040717 +23 42 67 100 157 278 538 1066 2083 3974 7413 13564 24385 43066 74636 126778 210895 343474 547799 856068 1311973 +17 16 18 31 63 120 202 307 471 908 2382 7072 20449 55217 139462 333322 762667 1686190 3627381 7632222 15772239 +9 2 1 27 108 270 523 838 1113 1134 566 -903 -2924 -2545 10761 66488 237145 685806 1755099 4125935 9088652 +7 20 45 85 149 263 494 1002 2141 4636 9866 20286 40042 75917 138994 248064 437359 774748 1404271 2642831 5192055 +25 44 73 122 216 406 783 1492 2738 4771 7832 12037 17171 22359 25576 22953 7831 -30490 -108365 -249844 -489206 +5 26 57 88 111 127 148 195 312 648 1704 4900 13688 35521 85085 189311 394807 778486 1462315 2633272 4569773 +9 15 28 69 177 418 894 1752 3193 5481 8952 14023 21201 31092 44410 61986 84777 113875 150516 196089 252145 +-8 -1 16 41 72 107 144 181 216 247 272 289 296 291 272 237 184 111 16 -103 -248 +19 32 57 104 199 399 807 1587 2979 5314 9029 14682 22967 34729 50979 72909 101907 139572 187729 248444 324039 +5 3 0 -6 -19 -45 -92 -170 -291 -469 -720 -1062 -1515 -2101 -2844 -3770 -4907 -6285 -7936 -9894 -12195 +19 33 60 109 201 388 781 1587 3155 6031 11022 19269 32329 52266 81751 124171 183747 265661 376192 522861 714585 +13 25 43 70 112 192 375 813 1839 4173 9350 20546 44083 92094 187268 371602 723333 1390953 2662565 5106282 9848238 +16 33 58 92 149 259 468 837 1443 2386 3807 5923 9086 13874 21223 32610 50298 77655 119560 182910 277243 +10 17 28 57 142 355 820 1744 3460 6479 11556 19799 32896 53609 86792 141338 233654 393509 673404 1162981 2010426 +12 22 35 59 102 172 277 425 624 882 1207 1607 2090 2664 3337 4117 5012 6030 7179 8467 9902 +27 42 65 118 251 553 1157 2232 3950 6420 9614 13412 18140 26516 49054 117300 313917 837634 2137911 5184538 11990201 +20 47 90 157 266 463 848 1608 3060 5711 10346 18159 30946 51383 83416 132794 207780 320079 486026 728081 1076682 +11 15 30 71 165 376 860 1965 4387 9393 19139 37159 69195 124698 219589 381285 657667 1132755 1953604 3375703 5838449 +13 26 38 53 77 124 245 601 1615 4259 10577 24656 54514 115911 240113 489452 987549 1975872 3915636 7664879 14776079 +1 3 14 35 65 102 160 328 911 2706 7476 18700 42738 90769 182480 353978 675636 1292119 2509355 4976253 10049958 +0 9 29 81 213 525 1219 2699 5767 11991 24355 48332 93556 176366 323829 580822 1024172 1793204 3156883 5658162 10412313 +17 26 39 61 98 160 273 513 1090 2535 6078 14350 32597 70659 146042 288496 546607 997016 1756993 3001219 4983764 +14 35 72 134 232 388 659 1199 2400 5185 11579 25762 55912 117274 237038 461767 868274 1578991 2782986 4763846 7935632 +2 13 32 59 94 137 188 247 314 389 472 563 662 769 884 1007 1138 1277 1424 1579 1742 +-6 -6 10 58 151 307 565 1015 1873 3679 7786 17486 40472 94032 215754 485288 1068255 2304408 4883699 10195280 21012360 +12 28 52 87 156 320 706 1547 3236 6407 12098 22153 40229 74179 141357 279863 571507 1187397 2476601 5136472 10538777 +14 42 84 152 277 510 924 1627 2801 4788 8251 14446 25650 45800 81409 142837 246008 414678 683374 1101140 1736243 +-4 5 36 105 231 439 774 1347 2449 4785 9903 20943 43961 90419 182245 362688 719982 1438213 2903350 5916121 12103119 +10 8 16 49 129 289 589 1154 2237 4301 8105 14772 25814 43092 68700 104783 153332 216046 294414 390251 507023 +14 23 44 82 140 220 321 441 603 954 2041 5454 15141 39833 97146 220017 466132 930849 1763722 3187986 5521138 +19 28 30 29 44 129 416 1188 2988 6772 14115 27466 50399 87695 144891 226637 332833 451148 544300 530651 257630 +23 31 39 59 116 260 580 1211 2331 4158 6981 11320 18468 32034 61876 133343 307710 725396 1694506 3868100 8592743 +12 29 63 114 184 290 496 974 2104 4623 9833 19878 38100 69484 121202 203266 329300 517441 791379 1181546 1726464 +11 2 -15 -48 -114 -237 -433 -676 -830 -500 1321 7081 22505 60383 147877 339805 741589 1547198 3099561 5983662 11165960 +3 14 50 140 322 644 1177 2050 3526 6152 11035 20320 37975 71022 131392 238626 423693 734250 1241728 2050692 3310992 +10 28 68 140 254 420 648 948 1330 1804 2380 3068 3878 4820 5904 7140 8538 10108 11860 13804 15950 +10 26 52 86 134 223 414 815 1594 2992 5336 9052 14678 22877 34450 50349 71690 99766 136060 182258 240262 +10 7 1 7 68 277 807 1949 4158 8107 14749 25387 41752 66089 101251 150801 219122 311535 434425 595375 803308 +18 23 37 88 233 584 1346 2867 5700 10677 18995 32314 52867 83582 128216 191501 279302 398787 558609 769100 1042477 +14 21 23 16 -4 -41 -99 -182 -294 -439 -621 -844 -1112 -1429 -1799 -2226 -2714 -3267 -3889 -4584 -5356 +21 35 62 129 292 664 1472 3154 6498 12822 24222 44027 77895 136629 243054 447596 861211 1721101 3515958 7216069 14683862 +12 25 64 148 299 545 930 1531 2482 4005 6448 10330 16393 25661 39506 59721 88600 129025 184560 259552 359239 +17 18 17 12 -7 -49 -100 -92 129 824 2355 5132 9489 15461 22430 28604 30289 20910 -10267 -79764 -211927 +26 52 88 130 174 216 252 278 290 284 256 202 118 0 -156 -354 -598 -892 -1240 -1646 -2114 +8 29 63 121 224 405 715 1230 2059 3365 5448 9045 16277 33321 77294 192711 488472 1216862 2935481 6828532 15328488 +16 33 64 108 175 302 577 1176 2433 4988 10100 20297 40729 82034 166486 341120 705138 1465263 3043356 6277654 12785247 +-5 -2 15 68 207 530 1222 2622 5331 10380 19490 35487 62993 109594 187767 317929 533187 887242 1469801 2441742 4120851 +7 22 62 138 263 465 823 1536 3040 6205 12683 25553 50537 98261 188327 356366 665777 1226540 2224336 3964224 6934319 +7 22 49 91 163 308 637 1404 3133 6826 14302 28760 55760 105060 194310 356819 658076 1230467 2344492 4550830 8956014 +13 21 50 108 198 331 552 989 1955 4162 9159 20221 44162 95029 201507 421327 868273 1760839 3506560 6842958 13065390 +17 29 48 76 110 148 197 279 441 809 1804 4794 13746 38952 104757 264585 628665 1412989 3022544 6188184 12185166 +16 31 46 61 76 91 106 121 136 151 166 181 196 211 226 241 256 271 286 301 316 +8 17 32 50 61 56 43 78 343 1345 4388 12633 33413 83215 198256 456526 1022658 2236817 4785840 10023572 20554597 +25 52 94 152 221 284 312 290 310 801 3018 10023 28625 73214 173338 388683 838833 1763061 3642311 7451654 15187265 +5 23 54 109 219 451 935 1917 3872 7746 15450 30811 61331 121414 238406 464247 898411 1733121 3341050 6440929 12400487 +26 38 48 53 50 36 8 -37 -102 -190 -304 -447 -622 -832 -1080 -1369 -1702 -2082 -2512 -2995 -3534 +15 41 83 155 280 499 898 1662 3165 6105 11693 21905 39806 69955 118900 195772 312987 487065 739575 1098215 1598036 +-1 11 39 89 160 250 374 606 1166 2594 6114 14442 33624 77167 175032 392461 867845 1886013 4015037 8353159 16960836 +25 49 77 110 150 202 284 458 919 2229 5871 15448 39119 94370 217225 480047 1026198 2137894 4368794 8800331 17528385 +18 37 73 142 273 512 935 1680 3014 5460 10017 18503 34013 61360 107065 177843 275426 383827 442785 298508 -378975 +4 17 40 81 172 388 886 1988 4354 9335 19674 40850 83554 168068 331712 641057 1211304 2236133 4032468 7106023 12245232 +1 20 61 138 270 481 800 1261 1903 2770 3911 5380 7236 9543 12370 15791 19885 24736 30433 37070 44746 +12 24 53 102 172 262 369 488 612 732 837 914 948 922 817 612 284 -192 -843 -1698 -2788 +5 13 21 29 37 45 53 61 69 77 85 93 101 109 117 125 133 141 149 157 165 +-8 -14 -20 -9 46 183 457 947 1765 3091 5314 9468 18347 39030 88184 202717 460644 1021318 2201962 4621039 9461834 +8 19 39 73 124 203 351 672 1374 2813 5533 10293 18070 30025 47417 71448 103020 142383 188651 239161 288648 +17 32 47 62 77 92 107 122 137 152 167 182 197 212 227 242 257 272 287 302 317 +11 30 64 124 238 470 946 1891 3690 7005 13021 23982 44374 83549 161516 321489 656273 1361728 2840866 5898656 12093074 +11 22 25 14 -17 -73 -161 -295 -496 -775 -1075 -1104 146 5752 24433 79285 227593 602848 1498793 3529242 7918937 +8 21 49 92 150 223 311 414 532 665 813 976 1154 1347 1555 1778 2016 2269 2537 2820 3118 +16 30 62 122 235 454 872 1633 2942 5074 8382 13304 20369 30202 43528 61175 84076 113270 149902 195222 250583 +-3 8 41 122 302 669 1360 2573 4579 7734 12491 19412 29180 42611 60666 84463 115289 154612 204093 265598 341210 +12 25 46 89 172 330 643 1287 2634 5450 11268 23051 46318 90999 174433 326151 595424 1063039 1859434 3192221 5387304 +20 45 85 144 236 391 669 1193 2212 4205 8037 15178 27996 50135 86989 146283 238772 379069 586613 886788 1312204 +7 18 39 61 76 78 73 119 439 1686 5489 15473 39024 90162 193991 393315 758143 1398954 2484755 4267141 7111756 +1 -2 2 24 89 244 575 1245 2565 5110 9892 18602 33933 59996 102841 171095 276729 435966 670342 1007932 1484753 +13 27 50 87 148 248 407 650 1007 1513 2208 3137 4350 5902 7853 10268 13217 16775 21022 26043 31928 +10 4 -6 -26 -69 -153 -288 -434 -401 349 3049 10185 26338 59394 122217 234891 427648 744610 1248484 2026360 3196773 +12 34 81 161 280 442 649 901 1196 1530 1897 2289 2696 3106 3505 3877 4204 4466 4641 4705 4632 +14 11 6 5 19 64 161 336 620 1049 1664 2511 3641 5110 6979 9314 12186 15671 19850 24809 30639 +11 24 64 154 326 623 1113 1921 3286 5662 9923 17825 33046 63386 125071 250561 501785 991264 1914054 3593728 6545562 +3 0 10 54 162 384 804 1566 2949 5578 10934 22431 47467 101039 211757 431428 849851 1617128 2976734 5313904 9225716 +2 6 29 95 255 601 1280 2508 4584 7904 12975 20429 31037 45723 65578 91874 126078 169866 225137 294027 378923 +19 44 76 114 164 240 369 617 1173 2553 6021 14383 33430 74591 160067 333412 682278 1387741 2829485 5803531 11958283 +10 19 28 37 46 55 64 73 82 91 100 109 118 127 136 145 154 163 172 181 190 +15 27 43 54 53 47 74 235 763 2175 5601 13484 31055 69409 151802 326187 689327 1431483 2916207 5817834 11350665 +5 -2 -15 -36 -66 -95 -72 153 922 2903 7270 15933 31821 59220 104167 174900 282363 440764 668183 987226 1425720 +8 18 31 38 39 72 263 901 2544 6168 13381 26738 50211 89890 155017 259485 423968 678886 1068451 1656086 2531559 +-6 -9 -12 -15 -18 -21 -24 -27 -30 -33 -36 -39 -42 -45 -48 -51 -54 -57 -60 -63 -66 +-2 -6 -10 -11 -6 17 97 329 906 2176 4716 9425 17638 31263 52943 86245 135878 207942 310210 452445 646754 +27 38 46 63 112 227 453 846 1473 2412 3752 5593 8046 11233 15287 20352 26583 34146 43218 53987 66652 +3 10 24 45 73 108 150 199 255 318 388 465 549 640 738 843 955 1074 1200 1333 1473 +7 33 81 155 263 425 685 1131 1925 3341 5803 9907 16401 26085 39579 56891 76699 95241 104685 90827 29939 +11 19 33 59 108 212 454 1030 2383 5492 12475 27786 60464 128139 263828 526975 1020715 1917985 3499877 6210541 10734012 +28 55 98 159 252 413 706 1231 2155 3807 6903 13007 25428 51001 103817 213380 442709 928208 1965983 4195304 8982191 +14 33 69 134 259 509 1013 2033 4121 8447 17422 35786 72380 142871 273748 507953 912552 1588885 2685659 4415462 7075177 +7 9 14 16 6 -28 -101 -231 -439 -749 -1188 -1786 -2576 -3594 -4879 -6473 -8421 -10771 -13574 -16884 -20758 +17 29 48 86 171 362 792 1769 3985 8915 19539 41597 85697 170746 329371 616248 1120569 1984257 3427994 5787664 9564439 +8 13 31 84 223 546 1219 2500 4766 8543 14539 23680 37149 56428 83343 120112 169396 234353 318695 426748 563515 +5 21 44 77 146 318 724 1594 3328 6656 12981 25052 48179 92279 175131 327319 599455 1072399 1871330 3184671 5289032 +12 28 45 59 60 22 -112 -450 -1176 -2580 -5093 -9327 -16120 -26586 -42170 -64708 -96492 -140340 -199671 -278585 -381948 +-1 14 42 83 137 204 284 377 483 602 734 879 1037 1208 1392 1589 1799 2022 2258 2507 2769 +15 33 61 101 166 294 573 1184 2470 5054 10075 19728 38574 76716 157252 332959 721757 1578367 3432541 7345187 15367442 +7 1 0 18 76 215 519 1157 2477 5224 11018 23332 49370 103474 212993 427921 836035 1585699 2918884 5217198 9063704 +5 11 17 28 56 118 240 487 1066 2589 6642 16897 41149 94892 207413 431942 862227 1659103 3092311 5605138 9912558 +7 28 64 131 268 540 1039 1889 3269 5493 9245 16182 30312 60849 127676 271198 569483 1167754 2329742 4529493 8620100 +4 18 46 98 205 439 945 1993 4063 7996 15305 28882 54621 105004 206659 415703 848225 1740490 3568429 7286884 14811544 +6 11 18 35 66 117 221 486 1177 2858 6640 14603 30481 60716 115997 213400 379232 652653 1090102 1770483 2800972 +18 23 39 79 170 374 821 1762 3652 7281 14002 26181 48138 88080 161860 299832 558598 1040027 1920513 3493947 6232194 +24 37 56 92 163 294 517 871 1402 2163 3214 4622 6461 8812 11763 15409 19852 25201 31572 39088 47879 +19 29 34 32 21 -1 -36 -86 -153 -239 -346 -476 -631 -813 -1024 -1266 -1541 -1851 -2198 -2584 -3011 +12 23 49 104 213 417 785 1433 2550 4431 7517 12442 20087 31641 48669 73187 107744 155511 220377 307052 421177 +5 11 11 3 -18 -60 -115 -97 303 1920 6718 18961 47457 109829 240631 506810 1037285 2079649 4108537 8030811 15568212 +11 25 50 97 200 429 908 1853 3652 7011 13179 24238 43412 75340 126319 204746 322615 500627 783946 1286729 2309190 +11 28 70 154 315 628 1253 2512 5015 9871 19047 35969 66489 120365 213410 370453 629211 1045086 1696764 2692292 4175031 +25 44 70 105 151 206 260 291 261 112 -238 -899 -2013 -3758 -6352 -10057 -15183 -22092 -31202 -42991 -58001 +10 30 63 126 252 508 1034 2123 4370 8928 17929 35168 67220 125273 228105 406753 711362 1220134 2048615 3353738 5319460 +3 -7 -9 18 112 351 900 2092 4553 9381 18389 34422 61758 106603 177690 286992 450559 689489 1031043 1509914 2169660 +7 0 0 16 57 132 250 420 651 952 1332 1800 2365 3036 3822 4732 5775 6960 8296 9792 11457 +6 27 66 128 214 315 407 458 477 666 1793 6013 18563 51096 127960 297545 652000 1360261 2721540 5249326 9799676 +-7 -6 -3 -6 -23 -53 -66 35 477 1712 4551 10344 21213 40345 72352 123705 203249 322806 497873 748422 1099809 +-7 3 34 95 198 369 680 1324 2776 6111 13585 29632 62516 127086 249627 477176 896965 1679113 3171706 6110051 12065212 +1 0 -5 -10 -8 11 60 155 315 562 921 1420 2090 2965 4082 5481 7205 9300 11815 14802 18316 diff --git a/src/day9.rs b/src/day9.rs new file mode 100644 index 0000000..2620737 --- /dev/null +++ b/src/day9.rs @@ -0,0 +1,79 @@ +#[derive(Debug)] +struct Series { + data: Vec, +} + +impl Series { + pub fn extrapolate_next_value(&self) -> isize { + Series::extrapolate(&self.data) + } + + fn extrapolate(series: &Vec) -> isize { + // Build up the difference series. When all values are 0, go back, and extrapolate. + if Series::all_zeros(&series) { + return 0 + } + + // Calculate the differences, and extrapolate that. + let mut differences = Vec::new(); + for i in 0..series.len() - 1 { + differences.push(series[i + 1] - series[i]); + } + let next_value = Series::extrapolate(&differences); + next_value + series[series.len() - 1] + } + + fn all_zeros(series: &Vec) -> bool { + for value in series { + if *value != 0 { + return false + } + } + true + } +} + +impl std::str::FromStr for Series { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let data = s.split_ascii_whitespace().map(isize::from_str).collect::, _>>().map_err(|_| "cannot parse series"); + match data { + Ok(data) => Ok(Self { data }), + Err(reason) => Err(reason), + } + } +} + +fn sum_of_extrapolated_values(input: &str) -> isize { + let mut result = 0; + for line in input.lines() { + if let Ok(series) = line.parse::() { + result += series.extrapolate_next_value(); + } + } + result +} + +pub fn main() { + match std::fs::read_to_string("day9.input") { + Ok(input) => { + println!("part1 = {}", sum_of_extrapolated_values(&input)); + }, + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + static DATA: &str = "0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45"; + + #[test] + fn part1_example() { + assert_eq!(sum_of_extrapolated_values(DATA), 114); + } +} diff --git a/src/main.rs b/src/main.rs index 0889929..f342c5e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day7; +mod day9; fn main() { - day7::main() + day9::main() } From 190b5fe60e01ca17e5f44f36e82acf7012f4f93e Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 9 Dec 2023 12:50:14 +0100 Subject: [PATCH 083/120] Day 9, part 2: Straight-backwards. --- src/day9.rs | 67 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/src/day9.rs b/src/day9.rs index 2620737..5fe728a 100644 --- a/src/day9.rs +++ b/src/day9.rs @@ -3,34 +3,45 @@ struct Series { data: Vec, } -impl Series { - pub fn extrapolate_next_value(&self) -> isize { - Series::extrapolate(&self.data) +fn differences(series: &Vec) -> Vec { + let mut result = Vec::new(); + for i in 0..series.len() - 1 { + result.push(series[i + 1] - series[i]); } + result +} - fn extrapolate(series: &Vec) -> isize { - // Build up the difference series. When all values are 0, go back, and extrapolate. - if Series::all_zeros(&series) { - return 0 - } +fn extrapolate_next_value(series: &Vec) -> isize { + // Build up the difference series. When all values are 0, go back, and extrapolate. + if all_zeros(series) { + return 0 + } - // Calculate the differences, and extrapolate that. - let mut differences = Vec::new(); - for i in 0..series.len() - 1 { - differences.push(series[i + 1] - series[i]); - } - let next_value = Series::extrapolate(&differences); - next_value + series[series.len() - 1] + // Calculate the differences, and extrapolate that. + let differences = differences(series); + let next_value = extrapolate_next_value(&differences); + next_value + series[series.len() - 1] +} + +fn extrapolate_previous_value(series: &Vec) -> isize { + // Build up the difference series. When all values are 0, go back, and extrapolate. + if all_zeros(series) { + return 0 } - fn all_zeros(series: &Vec) -> bool { - for value in series { - if *value != 0 { - return false - } + // Calculate the differences, and extrapolate that. + let differences = differences(series); + let previous_value = extrapolate_previous_value(&differences); + series[0] - previous_value +} + +fn all_zeros(series: &Vec) -> bool { + for value in series { + if *value != 0 { + return false } - true } + true } impl std::str::FromStr for Series { @@ -45,11 +56,11 @@ impl std::str::FromStr for Series { } } -fn sum_of_extrapolated_values(input: &str) -> isize { +fn sum_of_extrapolated_values(input: &str, extrapolate: impl Fn(&Vec) -> isize) -> isize { let mut result = 0; for line in input.lines() { if let Ok(series) = line.parse::() { - result += series.extrapolate_next_value(); + result += extrapolate(&series.data); } } result @@ -58,7 +69,8 @@ fn sum_of_extrapolated_values(input: &str) -> isize { pub fn main() { match std::fs::read_to_string("day9.input") { Ok(input) => { - println!("part1 = {}", sum_of_extrapolated_values(&input)); + println!("part1 = {}", sum_of_extrapolated_values(&input, extrapolate_next_value)); + println!("part2 = {}", sum_of_extrapolated_values(&input, extrapolate_previous_value)) }, Err(reason) => println!("error = {}", reason) } @@ -74,6 +86,11 @@ mod tests { #[test] fn part1_example() { - assert_eq!(sum_of_extrapolated_values(DATA), 114); + assert_eq!(sum_of_extrapolated_values(DATA, extrapolate_next_value), 114); + } + + #[test] + fn part2_example() { + assert_eq!(sum_of_extrapolated_values(DATA, extrapolate_previous_value), 2); } } From bce4c898ab60284a46fbdd255da73c11878971ed Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 9 Dec 2023 13:31:03 +0100 Subject: [PATCH 084/120] Day 8, part 1: One step at a time. --- day8.input | 804 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/day8.rs | 86 ++++++ src/main.rs | 4 +- 3 files changed, 892 insertions(+), 2 deletions(-) create mode 100644 day8.input create mode 100644 src/day8.rs diff --git a/day8.input b/day8.input new file mode 100644 index 0000000..a9bf733 --- /dev/null +++ b/day8.input @@ -0,0 +1,804 @@ +LRRRLRRLLLRRRLRLRRLRRRLRLRRRLLLRRLRRLRRRLRRRLRLLRLRRLRRLLRRLRLRRRLRRLRRLRRLLRRRLRLRLRLRLLRRLLLRRLRLRRLRLLLLRRLRRRLRRLRRRLLRRRLRRLRRRLRLLRLRRLRRLLRRRLLLRLRRRLLLRRLLRRRLLRRLRRLRRLRLRRRLLRRRLRLLRLRRLLRLRRLRLLRLRRLRRRLLRRLLRRRLRRLRLRLRRRLRLRRRLRRRLRRLRRRLRLLRRRLLRRRR + +FLR = (SXT, CRV) +VGG = (FBP, THJ) +VSK = (TBN, GJB) +XMP = (PSF, QLH) +KHT = (JPM, BLF) +KMD = (TPH, JHR) +TTD = (RVT, MJX) +VKS = (DRS, QJV) +SFR = (GFR, XPS) +MVD = (RLP, VRP) +RJF = (TBK, FMB) +HFD = (JRL, QKG) +LVV = (PDP, SCV) +JRH = (GLG, LTF) +PVQ = (VRC, SHR) +GXN = (PXL, LFT) +NGT = (LFX, TNX) +MTF = (KLC, GXN) +DGS = (NNC, NGB) +SVK = (GXN, KLC) +TJD = (NFP, LJM) +CNM = (JQD, DVR) +XBM = (PHK, LCH) +MJD = (KLH, CQH) +LDQ = (PBC, RXJ) +BSF = (DTN, FNF) +SXX = (CFM, DCK) +LFL = (PRH, LJC) +RMT = (DLM, PGT) +VDK = (LLP, HRP) +CMB = (CFX, VRV) +LPC = (QXS, LHN) +QSL = (SNC, BSK) +XCV = (FXR, RVX) +KMF = (VMP, NVR) +VBM = (HFD, HFD) +SLN = (QLM, FMX) +SRD = (DKM, DPT) +SCN = (DGC, NNT) +MQD = (RFS, FBN) +KJX = (HNQ, TFD) +SDL = (GMG, QVG) +RDM = (NFS, KBG) +FCN = (CBM, FLR) +FCF = (LXM, LHJ) +NPR = (DCL, RPR) +CFX = (CKQ, CLR) +XLF = (MLJ, JCX) +RNK = (GML, MXK) +BNQ = (QJQ, NNQ) +KTF = (CLD, MFT) +LFV = (GFN, GFN) +TBK = (SRD, LCB) +JFS = (FPR, RMR) +DDV = (MXH, GQL) +VTK = (TGV, KJD) +XFQ = (QLM, FMX) +LFX = (TNR, DHR) +FJN = (DRD, MNV) +CMS = (GSK, FGT) +GLN = (LBM, LPJ) +VRC = (NXG, GXQ) +DXR = (GMR, KRJ) +QCX = (CNJ, NGT) +DKM = (LCR, HMK) +QNV = (XVH, NTQ) +ZZZ = (SJH, LBH) +SSG = (FLB, FTT) +JJC = (VGG, QFQ) +GBJ = (VNV, VPT) +NSF = (DMF, KQH) +GTL = (BKD, CFQ) +JMQ = (RXK, BMJ) +FNK = (QNN, JCR) +SGC = (LPC, VHP) +HFP = (VTD, CNL) +HNQ = (FPF, BBS) +JHH = (MDT, TRH) +XXS = (PSG, DRP) +KMC = (BRR, FTJ) +LCB = (DPT, DKM) +QXC = (VGL, PLT) +RLP = (JNB, TGL) +MMK = (HDV, XMP) +HMK = (CTP, TGK) +PQR = (FDC, VNX) +PQN = (BKT, XDX) +SMQ = (BBT, MGM) +TGK = (NND, JGM) +QNQ = (GML, MXK) +JBG = (MDT, TRH) +MLJ = (HFV, XPP) +STB = (QXR, SCN) +LQL = (NCV, NVX) +BGT = (GGT, MKM) +DLM = (JFS, JMN) +KNP = (KQH, DMF) +XDT = (PCS, MHT) +GFR = (GLP, KPP) +PHF = (FCF, NLH) +RFH = (KSC, QRN) +KBG = (SQT, CRH) +RQJ = (VXF, SDQ) +MDT = (RSL, RSL) +KRK = (BKN, RJR) +BMK = (SGN, TTC) +TVQ = (LDC, JRP) +TTH = (NVH, RJF) +VDJ = (HCM, GHQ) +RVX = (JKT, QMK) +MRK = (DQF, BSL) +QSH = (RJR, BKN) +DLB = (PTM, CBH) +JML = (JPL, FHX) +FRK = (CMF, TVQ) +DRP = (PKD, TJD) +NDC = (FCK, BKK) +PCD = (VBM, MBD) +LXN = (FCX, FLM) +SCV = (QXJ, BSF) +NJM = (MNF, QHM) +CHX = (VNV, VPT) +XJC = (CXR, SGJ) +NRR = (PHQ, PVN) +TMN = (PQS, XHL) +PSG = (PKD, TJD) +GHV = (QHB, CDM) +XPV = (BNG, KHF) +HJF = (HSJ, QQT) +NVR = (DGS, JTZ) +BVV = (SSG, KRB) +LQG = (TNQ, FRM) +GMG = (XHX, MRK) +DBD = (SFR, GVF) +TTC = (DBD, GPK) +JFR = (MJB, GSV) +PDF = (BJJ, DSX) +DMF = (JDD, PVS) +NSJ = (NXV, DVS) +XHX = (BSL, DQF) +PHS = (NLV, SHG) +FNL = (KDB, NCN) +PMS = (BNK, QPG) +JDD = (DDB, HJF) +FMH = (JMK, STT) +HBP = (GDC, JJG) +JCR = (GHS, XBM) +RGV = (KNM, BTG) +PQC = (SKV, LQL) +TPG = (BRK, KJX) +BNJ = (DVS, NXV) +FGL = (SVK, MTF) +JNB = (PKM, SXB) +TXQ = (HRL, NJN) +LFB = (DQV, XHD) +SNC = (BKP, XDT) +LBK = (LPP, XCT) +JPL = (KMC, SRL) +GVS = (JHG, HPG) +QSF = (PVN, PHQ) +RPR = (FFH, FNS) +VLN = (RNJ, BFQ) +TLX = (PHF, PTJ) +QBN = (KNP, NSF) +BCH = (JCX, MLJ) +HPB = (MCN, TMN) +GQH = (MTF, SVK) +FMX = (PTC, DGD) +RGK = (RVT, MJX) +VTN = (HLN, GKV) +HTM = (JBC, NMR) +FBP = (KXM, MQL) +CLM = (HTM, QVS) +TLJ = (XRB, DXM) +NTH = (STT, JMK) +NGB = (XTC, PQN) +XHS = (XFX, DGB) +VBB = (VFQ, MVD) +RXH = (KBQ, HGL) +PCS = (RRH, MBP) +BNG = (PJQ, SBX) +XVH = (DFC, RTT) +GMC = (KJX, BRK) +LXD = (KKP, DLF) +GNB = (SCP, RFM) +BRK = (TFD, HNQ) +PQS = (SMQ, FGF) +LKN = (SCN, QXR) +HPV = (KKH, PMS) +GHQ = (VBB, RCB) +FJF = (CXR, SGJ) +GVF = (GFR, XPS) +DCK = (JMP, XCV) +PKM = (HRR, HJL) +TGJ = (CJF, NSR) +NNQ = (BVV, FLD) +JRP = (SLN, XFQ) +CJT = (CVN, LFB) +HLG = (TCH, LTD) +FNX = (RMT, NGD) +QXR = (NNT, DGC) +BRR = (SQF, XHS) +XXB = (TGV, KJD) +FDC = (LDQ, GGD) +XGP = (NJH, VJM) +FTT = (MXV, DPG) +LPP = (LFJ, QJP) +BJL = (GTK, MJJ) +FNS = (KMD, TSC) +LHJ = (MJD, VCP) +HFV = (STB, LKN) +TPR = (QNN, JCR) +RVT = (DFN, NQL) +LVB = (FQT, KHM) +VCL = (LQQ, DTB) +GXQ = (TGJ, XDD) +GSX = (VTM, GPQ) +PTM = (STQ, SVD) +NFS = (CRH, SQT) +XFX = (RXH, TFB) +QLH = (DVK, XRH) +MJB = (HHV, HFP) +QQB = (TMN, MCN) +BKN = (FNX, FMQ) +RKP = (HPT, SDL) +CKD = (TTD, RGK) +QKX = (GKP, TKQ) +HFR = (DSM, MQD) +DMC = (NMD, RFR) +XPS = (GLP, KPP) +CLZ = (TKJ, FMR) +KDB = (XTN, GVS) +BPQ = (BMK, MNL) +PXL = (VCL, QVT) +SQT = (GHH, SNV) +FBN = (HKK, DXR) +SRN = (KLQ, LQC) +KXD = (QJQ, NNQ) +HLN = (NSJ, BNJ) +KQH = (JDD, PVS) +BKB = (KHT, PVC) +RNJ = (QNV, GRM) +BDQ = (BNT, TLJ) +NRQ = (CMB, HLJ) +SMG = (CNJ, NGT) +MKM = (HNP, SJN) +MCL = (RDS, HXK) +QJQ = (BVV, FLD) +XSH = (KLV, NHL) +NXK = (RJF, NVH) +TGV = (LPT, JSX) +XDV = (LJS, PPL) +KVS = (BDS, LFL) +VXB = (QFQ, VGG) +SCP = (LTB, SJQ) +FGH = (NMD, RFR) +RJH = (MCR, MMP) +VMP = (DGS, DGS) +DQS = (GMP, TBV) +FPL = (LCL, TFF) +XXT = (VMC, QPR) +QHM = (JSD, DDL) +BSL = (NXK, TTH) +PRH = (JHX, RHL) +FHX = (KMC, SRL) +SGK = (RQJ, QKL) +NGD = (DLM, PGT) +PVN = (BXC, LXD) +SJN = (GJD, XRV) +KFV = (XNG, FTZ) +JRL = (XDM, TLX) +RSM = (TCS, MMH) +CJF = (BDB, GDR) +XRB = (FQP, GSX) +CBH = (SVD, STQ) +BNT = (XRB, DXM) +BCQ = (LSF, VDJ) +VHG = (HTK, MFH) +DCG = (KKH, KKH) +TDH = (LMN, ZZZ) +TFF = (XHP, LQK) +TRH = (RSL, JDM) +MCR = (GCK, XLT) +KCB = (CMF, TVQ) +HMV = (FCK, BKK) +LQC = (CHN, FQJ) +SNT = (NRQ, SXL) +HXP = (FRK, KCB) +SKV = (NCV, NVX) +TBV = (XKQ, HCL) +XTN = (JHG, HPG) +SCK = (SDL, HPT) +KHM = (HMP, SPQ) +KDT = (GSK, FGT) +GKZ = (VTN, QMF) +TPH = (XXP, CKD) +PFQ = (THX, SNX) +GCJ = (VGL, PLT) +MNF = (DDL, JSD) +BDS = (LJC, PRH) +KJD = (LPT, JSX) +PRV = (MBC, NPR) +KTD = (FXV, PFQ) +NVH = (FMB, TBK) +MJX = (NQL, DFN) +MBV = (CFQ, BKD) +LBM = (SFN, XDV) +FXR = (QMK, JKT) +CHN = (GBJ, CHX) +GGD = (PBC, RXJ) +DTB = (QKX, HFC) +NQL = (JKJ, NJM) +DQF = (NXK, TTH) +QXJ = (DTN, FNF) +BGS = (PFQ, FXV) +FQP = (GPQ, VTM) +DPT = (HMK, LCR) +PHK = (DNF, GHV) +STQ = (FCN, NNS) +LCL = (XHP, LQK) +QJP = (FJN, CCV) +GJD = (BCQ, VBR) +GMR = (BJX, XNH) +JKT = (VTR, QKB) +RTT = (PRV, LNL) +LNL = (NPR, MBC) +DRD = (JRH, KVD) +SHR = (NXG, GXQ) +RXK = (LFQ, QSK) +VBR = (LSF, VDJ) +BKT = (VHQ, KPD) +QJV = (CMS, KDT) +CPH = (NRQ, SXL) +CSM = (QRN, KSC) +KLV = (GMC, TPG) +HDR = (RQJ, QKL) +TNX = (DHR, TNR) +VHQ = (CXX, CVL) +FCX = (FNK, TPR) +MBP = (BPV, NNB) +KKH = (BNK, BNK) +LQQ = (QKX, HFC) +QKL = (SDQ, VXF) +BKP = (PCS, MHT) +JTB = (BRS, XXS) +HRL = (HTC, FSM) +FXV = (SNX, THX) +TNR = (PVQ, KSF) +GLG = (TXQ, HSH) +PGV = (RFM, SCP) +FLM = (TPR, FNK) +JHX = (QSF, NRR) +PVC = (JPM, BLF) +GML = (VKS, CPT) +PDD = (PGV, GNB) +FMQ = (NGD, RMT) +XNG = (XMC, GVV) +LNH = (PBB, PBB) +XFN = (HTK, HTK) +LFT = (VCL, QVT) +DVS = (RGV, PMX) +VGL = (XBL, TQB) +MNV = (JRH, KVD) +LTB = (XXT, CPL) +NKN = (XKF, FQX) +FQX = (RDJ, CNR) +BJJ = (HFR, KBJ) +CFM = (JMP, XCV) +FQT = (HMP, SPQ) +PLT = (XBL, TQB) +QSN = (GQL, MXH) +HKV = (JBG, JHH) +LLC = (SHG, NLV) +SXT = (QPN, TFS) +MBD = (HFD, VCZ) +HMP = (CJN, SGC) +KBF = (LML, QVC) +HNC = (RFH, CSM) +JMP = (FXR, RVX) +JSX = (CNF, XKM) +VCZ = (QKG, JRL) +CSQ = (BFQ, RNJ) +GMP = (XKQ, HCL) +GLM = (PTM, CBH) +VPT = (BGT, BPH) +RJR = (FMQ, FNX) +KQT = (XJC, FJF) +NNS = (FLR, CBM) +VKV = (KNP, NSF) +NCV = (QFS, STN) +XCT = (LFJ, QJP) +VJK = (BKB, XJM) +FNF = (LNH, JNJ) +JHG = (VSK, MML) +HLJ = (VRV, CFX) +GRM = (XVH, NTQ) +FCK = (BDQ, GQS) +DRS = (CMS, KDT) +DVK = (SRC, VJK) +PDP = (QXJ, BSF) +THX = (FGM, XVD) +DNF = (QHB, CDM) +GKH = (HXK, RDS) +RFS = (HKK, DXR) +GKP = (GTL, MBV) +MXH = (BLG, CLM) +PQQ = (JJG, GDC) +RKC = (BCH, XLF) +QVG = (XHX, MRK) +DGC = (PNS, JTB) +HTC = (RSF, TTS) +FDV = (FQX, XKF) +CNF = (XGP, BNN) +HJL = (QJR, RJH) +QNN = (GHS, XBM) +BPV = (GGQ, GQJ) +SVD = (FCN, NNS) +XKF = (RDJ, CNR) +XSR = (LKM, PTB) +VTR = (SSL, DQS) +DPG = (LFV, TLP) +XTC = (BKT, XDX) +QFS = (FRQ, XPV) +RDJ = (CJT, MKS) +CXR = (NDC, HMV) +LML = (GLB, RSM) +NKG = (LBK, MSS) +CLD = (XXB, VTK) +VXF = (NQS, JFR) +MCN = (PQS, XHL) +GQD = (DVR, JQD) +FTZ = (GVV, XMC) +SNV = (SNT, CPH) +NCN = (XTN, GVS) +QKB = (DQS, SSL) +GSV = (HHV, HFP) +LCH = (GHV, DNF) +KBJ = (DSM, MQD) +FRQ = (KHF, BNG) +BFQ = (QNV, GRM) +HSJ = (SVR, RPX) +XSM = (SHJ, VMR) +VDX = (XNG, XNG) +HCL = (MJQ, JML) +NJH = (NDP, VTX) +LCX = (LCL, TFF) +VNX = (LDQ, GGD) +HPT = (QVG, GMG) +NSR = (GDR, BDB) +XRH = (SRC, VJK) +CPL = (VMC, QPR) +XHD = (KRK, QSH) +GGQ = (PQC, RVF) +LSF = (GHQ, HCM) +XHL = (SMQ, FGF) +HXK = (NTH, FMH) +VNV = (BPH, BGT) +MHX = (VMP, VMP) +MST = (HVL, PLQ) +JHR = (XXP, CKD) +FMB = (SRD, LCB) +FTJ = (XHS, SQF) +VTX = (MRS, GRS) +CXX = (HDG, KQT) +SFN = (LJS, PPL) +STT = (JTP, VDK) +RVK = (MFT, CLD) +XJM = (PVC, KHT) +PMX = (KNM, BTG) +NFP = (QSL, GBP) +HRR = (RJH, QJR) +VRV = (CLR, CKQ) +MSS = (XCT, LPP) +KHF = (PJQ, SBX) +SJH = (BLH, MDV) +BNK = (VVF, VVF) +FFH = (KMD, TSC) +LFJ = (FJN, CCV) +TFD = (FPF, BBS) +CJN = (LPC, VHP) +TFB = (HGL, KBQ) +TNQ = (KNF, MGF) +NLV = (KTF, RVK) +CBM = (CRV, SXT) +NTQ = (DFC, RTT) +DSM = (RFS, FBN) +DLF = (QXC, GCJ) +XXN = (XLF, BCH) +TFV = (DVV, PDD) +TKJ = (DNV, HXP) +JGM = (QCX, SMG) +HRP = (MMK, DDN) +FRT = (LFL, BDS) +CLR = (STS, SRN) +NQS = (GSV, MJB) +CQH = (GQD, CNM) +PPL = (JGT, HKV) +PVS = (HJF, DDB) +LJC = (JHX, RHL) +MGM = (PHS, LLC) +VJH = (PLQ, HVL) +LDC = (SLN, XFQ) +TQB = (VLN, CSQ) +BLF = (QNQ, RNK) +HPG = (VSK, MML) +BTG = (FNL, HMQ) +CRH = (GHH, SNV) +DML = (DVV, PDD) +QPG = (VVF, CLZ) +RSF = (QSN, DDV) +DNV = (FRK, KCB) +CVN = (DQV, XHD) +TCH = (DLB, GLM) +LJM = (GBP, QSL) +QMF = (GKV, HLN) +PTJ = (NLH, FCF) +KKP = (QXC, GCJ) +RHL = (NRR, QSF) +PGT = (JMN, JFS) +PTC = (DMC, FGH) +BRS = (DRP, PSG) +VHP = (LHN, QXS) +GKV = (NSJ, BNJ) +MNL = (SGN, TTC) +FSD = (VPX, GLN) +RMR = (RKP, SCK) +MDV = (DML, TFV) +VFQ = (VRP, RLP) +XBL = (VLN, CSQ) +NMD = (RKC, XXN) +MJQ = (FHX, JPL) +DPN = (PDP, SCV) +XNH = (NKN, FDV) +NDP = (MRS, GRS) +KPD = (CVL, CXX) +DFC = (PRV, LNL) +KBQ = (LQT, LNC) +NXG = (TGJ, XDD) +XRV = (VBR, BCQ) +JDM = (VDX, KFV) +QHB = (FSD, PML) +GDR = (BPQ, SBC) +SDQ = (NQS, JFR) +VJM = (VTX, NDP) +QLT = (VMR, SHJ) +STN = (XPV, FRQ) +AAA = (LBH, SJH) +MJJ = (HDR, SGK) +STS = (LQC, KLQ) +CFQ = (BNQ, KXD) +PML = (GLN, VPX) +KLC = (PXL, LFT) +PLQ = (HBP, PQQ) +NLH = (LHJ, LXM) +DVV = (GNB, PGV) +TGL = (PKM, SXB) +MRS = (NKG, GMD) +HMQ = (NCN, KDB) +TBN = (FPL, LCX) +HNP = (XRV, GJD) +DGD = (DMC, FGH) +PTB = (PDF, GDT) +TCS = (BGS, KTD) +QRN = (RTJ, XSK) +DDN = (XMP, HDV) +PJM = (MJJ, GTK) +NND = (QCX, SMG) +LTD = (GLM, DLB) +DDL = (VXB, JJC) +HCM = (VBB, RCB) +GQJ = (PQC, RVF) +MGF = (DPN, LVV) +LXT = (DCG, HPV) +BXC = (KKP, DLF) +HPK = (QVC, LML) +JBC = (FCT, JMQ) +JGT = (JBG, JHH) +BJX = (FDV, NKN) +KSF = (SHR, VRC) +JJG = (QLT, XSM) +GBP = (SNC, BSK) +GJB = (FPL, LCX) +LJS = (HKV, JGT) +LQT = (QQB, HPB) +GGT = (HNP, SJN) +KLH = (GQD, CNM) +KSC = (RTJ, XSK) +SXL = (HLJ, CMB) +BBT = (PHS, LLC) +MXV = (LFV, TLP) +GQS = (TLJ, BNT) +PSF = (XRH, DVK) +KTC = (RFH, CSM) +HSH = (NJN, HRL) +HGG = (HPK, KBF) +PKD = (LJM, NFP) +HFC = (GKP, TKQ) +VLA = (QMF, VTN) +JKJ = (MNF, QHM) +FQJ = (GBJ, CHX) +JPM = (QNQ, RNK) +MMP = (GCK, XLT) +NNB = (GGQ, GQJ) +QMK = (QKB, VTR) +FRM = (KNF, MGF) +GPK = (GVF, SFR) +GTK = (HDR, SGK) +VCP = (KLH, CQH) +CPT = (QJV, DRS) +BPH = (MKM, GGT) +GRS = (NKG, GMD) +LTF = (HSH, TXQ) +SJQ = (XXT, CPL) +DGB = (TFB, RXH) +XMC = (KLM, SXX) +SRC = (BKB, XJM) +VTD = (MRN, NPH) +SSL = (TBV, GMP) +QVS = (NMR, JBC) +KLQ = (FQJ, CHN) +XDM = (PTJ, PHF) +JQD = (CFN, JTS) +BDB = (BPQ, SBC) +XKM = (XGP, BNN) +GQL = (CLM, BLG) +JTP = (HRP, LLP) +NMR = (FCT, JMQ) +RFR = (XXN, RKC) +XPT = (TCH, LTD) +TTS = (DDV, QSN) +LNC = (HPB, QQB) +NJN = (FSM, HTC) +FLD = (KRB, SSG) +KNF = (DPN, LVV) +BMJ = (LFQ, QSK) +GLB = (MMH, TCS) +XDD = (CJF, NSR) +MXK = (CPT, VKS) +DCL = (FNS, FFH) +PBC = (MHX, MHX) +RFM = (LTB, SJQ) +KLM = (DCK, CFM) +XVD = (RDM, QQJ) +RDS = (NTH, FMH) +RVF = (SKV, LQL) +BLG = (QVS, HTM) +CNR = (CJT, MKS) +LFQ = (HNC, KTC) +FPR = (SCK, RKP) +LQK = (CDR, XSR) +QVC = (RSM, GLB) +DDB = (HSJ, QQT) +SQV = (QMF, VTN) +HDG = (XJC, FJF) +LCR = (CTP, TGK) +JTZ = (NGB, NNC) +FSM = (RSF, TTS) +BSK = (BKP, XDT) +GHS = (LCH, PHK) +SRL = (FTJ, BRR) +BNN = (NJH, VJM) +PNS = (XXS, BRS) +PJA = (XMC, GVV) +XXF = (FDC, VNX) +JMN = (FPR, RMR) +GHH = (CPH, SNT) +QXS = (LXT, NVN) +BKD = (KXD, BNQ) +MKS = (LFB, CVN) +XKQ = (MJQ, JML) +PJQ = (TQP, LVB) +QPR = (GKH, MCL) +MFH = (SQV, GKZ) +SBC = (BMK, MNL) +THJ = (MQL, KXM) +XHP = (XSR, CDR) +HDV = (QLH, PSF) +RSL = (VDX, VDX) +MMH = (KTD, BGS) +HVL = (HBP, PQQ) +FGF = (BBT, MGM) +RRH = (NNB, BPV) +NHL = (GMC, TPG) +NNC = (PQN, XTC) +KPP = (XFN, VHG) +VTM = (HGG, CTC) +XDX = (VHQ, KPD) +SPQ = (CJN, SGC) +GDC = (XSM, QLT) +QQJ = (KBG, NFS) +MML = (TBN, GJB) +QFQ = (FBP, THJ) +VVF = (FMR, TKJ) +JJQ = (KLV, NHL) +PHQ = (BXC, LXD) +KNM = (FNL, HMQ) +GCK = (PQR, XXF) +DSX = (KBJ, HFR) +TKQ = (MBV, GTL) +JNJ = (PBB, TDH) +CVL = (KQT, HDG) +SHJ = (QBN, VKV) +NNT = (PNS, JTB) +CRV = (QPN, TFS) +PBB = (LMN, LMN) +GDT = (BJJ, DSX) +FGM = (QQJ, RDM) +BLH = (DML, TFV) +FMR = (DNV, HXP) +FPF = (VJH, MST) +KXM = (BJL, PJM) +FCT = (BMJ, RXK) +FLB = (MXV, DPG) +SXB = (HRR, HJL) +CMF = (JRP, LDC) +HKK = (KRJ, GMR) +TSC = (TPH, JHR) +QKG = (XDM, TLX) +QVT = (DTB, LQQ) +SHG = (KTF, RVK) +GMD = (MSS, LBK) +NXV = (PMX, RGV) +KRB = (FTT, FLB) +CTC = (KBF, HPK) +DTN = (LNH, LNH) +DXM = (GSX, FQP) +LBH = (BLH, MDV) +FGT = (HLG, XPT) +QPN = (XSH, JJQ) +DQV = (KRK, QSH) +LMN = (LBH, SJH) +SGJ = (HMV, NDC) +LPJ = (XDV, SFN) +MHT = (RRH, MBP) +TFS = (JJQ, XSH) +QLM = (PTC, DGD) +GSK = (HLG, XPT) +LXM = (VCP, MJD) +GLP = (XFN, XFN) +BBS = (MST, VJH) +SVR = (MCS, LQG) +NPH = (FGL, GQH) +NVN = (DCG, HPV) +VSA = (FMR, TKJ) +MCS = (TNQ, FRM) +JSD = (JJC, VXB) +QQT = (SVR, RPX) +CNL = (MRN, NPH) +HTK = (SQV, SQV) +JMK = (VDK, JTP) +VMC = (GKH, MCL) +RCB = (MVD, VFQ) +LHN = (LXT, NVN) +RXJ = (MHX, KMF) +VMR = (QBN, VKV) +DVR = (JTS, CFN) +XXP = (TTD, RGK) +BKK = (GQS, BDQ) +CCV = (DRD, MNV) +GPQ = (CTC, HGG) +SBX = (TQP, LVB) +SQF = (XFX, DGB) +SGN = (GPK, DBD) +LPT = (XKM, CNF) +CFN = (KVS, FRT) +NVX = (STN, QFS) +KRJ = (XNH, BJX) +VRP = (TGL, JNB) +LLP = (DDN, MMK) +NBQ = (FCX, FLM) +DFN = (JKJ, NJM) +RPX = (MCS, LQG) +QJR = (MCR, MMP) +CNJ = (LFX, TNX) +GVV = (SXX, KLM) +MFT = (VTK, XXB) +QKA = (JRL, QKG) +SNX = (FGM, XVD) +JTS = (KVS, FRT) +XPP = (LKN, STB) +XSK = (LXN, NBQ) +CPA = (NNC, NGB) +MBC = (RPR, DCL) +CTP = (NND, JGM) +MRN = (FGL, GQH) +CDM = (PML, FSD) +LKM = (GDT, PDF) +TQP = (FQT, KHM) +RTJ = (LXN, NBQ) +CDR = (LKM, PTB) +HHV = (CNL, VTD) +QSK = (KTC, HNC) +KVD = (GLG, LTF) +VPX = (LBM, LPJ) +GFN = (VBM, VBM) +JCX = (HFV, XPP) +DHR = (PVQ, KSF) +XLT = (XXF, PQR) +CKQ = (STS, SRN) +MQL = (PJM, BJL) +TLP = (GFN, PCD) +HGL = (LNC, LQT) diff --git a/src/day8.rs b/src/day8.rs new file mode 100644 index 0000000..31adcf1 --- /dev/null +++ b/src/day8.rs @@ -0,0 +1,86 @@ +use std::collections::HashMap; + +struct Network { + nodes: HashMap +} + +impl Network { + fn count_steps(&self, from: &str, to: &str, instructions: &[char]) -> Option { + let mut steps = 0; + let mut current = from; + let mut ip = 0; + while current != to { + if let Some((left, right)) = self.nodes.get(current) { + let next = if instructions[ip] == 'L' { left } else { right }; + current = next; + steps += 1; + ip = (ip + 1) % instructions.len(); + } else { + return None + } + } + Some(steps) + } +} + +impl std::str::FromStr for Network { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let mut nodes = HashMap::new(); + for line in s.lines().filter(|line| !line.is_empty()) { + if let Some((name, connections)) = line.split_once(" = ") { + let connections = connections.trim_matches(|c| c == '(' || c == ')'); + if let Some((left, right)) = connections.split_once(", ") { + nodes.insert(name.to_string(), (left.to_string(), right.to_string())); + } else { + return Err("cannot parse connections") + } + } else { + println!("cannot parse node: {}", line); + return Err("cannot parse node") + } + } + Ok(Self { nodes }) + } +} + +pub fn main() { + match std::fs::read_to_string("day8.input") { + Ok(input) => { + // First line: Instructions + // Second and following (non-empty) lines: Network nodes. + if let Some((instructions, network_data)) = input.split_once('\n') { + let network = network_data.parse::().unwrap(); + + println!("number of steps from AAA to ZZZ (part 1) = {}", network.count_steps("AAA", "ZZZ", &instructions.chars().collect::>()).unwrap()); + } + }, + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example1() { + static NETWORK_DATA: &str = "AAA = (BBB, CCC) +BBB = (DDD, EEE) +CCC = (ZZZ, GGG) +DDD = (DDD, DDD) +EEE = (EEE, EEE) +GGG = (GGG, GGG) +ZZZ = (ZZZ, ZZZ)"; + assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_steps("AAA", "ZZZ", &['R', 'L']), Some(2)) + } + + #[test] + fn part1_example2() { + static NETWORK_DATA: &str = "AAA = (BBB, BBB) +BBB = (AAA, ZZZ) +ZZZ = (ZZZ, ZZZ)"; + assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_steps("AAA", "ZZZ", &['L', 'L', 'R']), Some(6)) + } +} diff --git a/src/main.rs b/src/main.rs index f342c5e..e866b45 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day9; +mod day8; fn main() { - day9::main() + day8::main() } From 8da662d426f320d6de901e337772dcf0e1f873ec Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 9 Dec 2023 13:56:02 +0100 Subject: [PATCH 085/120] Day 8, part 2: ... and now in parallel, but also not. Simulating these ghost steps seems to take a long long long time, and just running it in parallel probably doesn't help. New plan therefore: Calculate the cycle length for each starting point independently, and then calculate the KGV for the cycle lengths. --- src/day8.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/day8.rs b/src/day8.rs index 31adcf1..1b7482c 100644 --- a/src/day8.rs +++ b/src/day8.rs @@ -21,6 +21,33 @@ impl Network { } Some(steps) } + + fn count_ghost_steps(&self, instructions: &[char]) -> Option { + let mut steps = 0; + let mut current = self.nodes.keys().filter(|name| name.ends_with('A')).collect::>(); + let mut ip = 0; + while !Self::all_end_with_z(¤t) { + // Process all nodes + for node in current.iter_mut() { + if let Some((left, right)) = self.nodes.get(*node) { + let next = if instructions[ip] == 'L' { left } else { right }; + *node = next; + } else { + return None + } + } + steps += 1; + ip = (ip + 1) % instructions.len(); + if ip == 0 { + println!("steps = {}, current = {:?}", steps, current) + } + } + Some(steps) + } + + fn all_end_with_z(nodes: &[&String]) -> bool { + nodes.iter().all(|name| name.ends_with('Z')) + } } impl std::str::FromStr for Network { @@ -54,6 +81,7 @@ pub fn main() { let network = network_data.parse::().unwrap(); println!("number of steps from AAA to ZZZ (part 1) = {}", network.count_steps("AAA", "ZZZ", &instructions.chars().collect::>()).unwrap()); + println!("number of ghost steps (part 2) = {}", network.count_ghost_steps(&instructions.chars().collect::>()).unwrap()); } }, Err(reason) => println!("error = {}", reason) @@ -83,4 +111,17 @@ BBB = (AAA, ZZZ) ZZZ = (ZZZ, ZZZ)"; assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_steps("AAA", "ZZZ", &['L', 'L', 'R']), Some(6)) } + + #[test] + fn part2_example1() { + static NETWORK_DATA: &str = "11A = (11B, XXX) +11B = (XXX, 11Z) +11Z = (11B, XXX) +22A = (22B, XXX) +22B = (22C, 22C) +22C = (22Z, 22Z) +22Z = (22B, 22B) +XXX = (XXX, XXX)"; + assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_ghost_steps(&['L', 'R']), Some(6)) + } } From 2e04643fa9188b183f3f3d14a9dad3e593860d56 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sat, 9 Dec 2023 14:14:42 +0100 Subject: [PATCH 086/120] Day 8, part 2: Why walk when you can just calculate it. --- Cargo.lock | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/day8.rs | 40 +++++++++++++++++++++++--- 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d90a9bb..ce103b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,10 +7,93 @@ name = "adventofcode" version = "0.1.0" dependencies = [ "muldiv", + "num", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "muldiv" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956787520e75e9bd233246045d19f42fb73242759cc57fba9611d940ae96d4b0" + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] diff --git a/Cargo.toml b/Cargo.toml index 5979cfe..295b843 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] muldiv = "1.0.1" +num = "0.4.1" [[bin]] name = "adventofcode" diff --git a/src/day8.rs b/src/day8.rs index 1b7482c..81abb06 100644 --- a/src/day8.rs +++ b/src/day8.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use num::integer::lcm; struct Network { nodes: HashMap @@ -48,6 +49,36 @@ impl Network { fn all_end_with_z(nodes: &[&String]) -> bool { nodes.iter().all(|name| name.ends_with('Z')) } + + fn cycle_length(&self, from: &str, instructions: &[char]) -> Option { + let mut steps = 0; + let mut current = from; + let mut ip = 0; + while !current.ends_with('Z') { + if let Some((left, right)) = self.nodes.get(current) { + let next = if instructions[ip] == 'L' { left } else { right }; + current = next; + steps += 1; + ip = (ip + 1) % instructions.len(); + } else { + return None + } + } + Some(steps) + } + + fn calculate_ghost_steps(&self, instructions: &[char]) -> Option { + let cycle_lengths = self.nodes.keys() + .filter_map(|name| if name.ends_with('A') { Some(self.cycle_length(name, instructions)) } else { None }) + .map(|cycle_length| cycle_length.unwrap()) + .collect::>(); + + let mut result = lcm(cycle_lengths[0], cycle_lengths[1]); + for cycle_length in cycle_lengths.iter().skip(2) { + result = lcm(result, *cycle_length); + } + Some(result) + } } impl std::str::FromStr for Network { @@ -81,7 +112,7 @@ pub fn main() { let network = network_data.parse::().unwrap(); println!("number of steps from AAA to ZZZ (part 1) = {}", network.count_steps("AAA", "ZZZ", &instructions.chars().collect::>()).unwrap()); - println!("number of ghost steps (part 2) = {}", network.count_ghost_steps(&instructions.chars().collect::>()).unwrap()); + println!("number of ghost steps (part 2, calculated) = {}", network.calculate_ghost_steps(&instructions.chars().collect::>()).unwrap()); } }, Err(reason) => println!("error = {}", reason) @@ -101,7 +132,7 @@ DDD = (DDD, DDD) EEE = (EEE, EEE) GGG = (GGG, GGG) ZZZ = (ZZZ, ZZZ)"; - assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_steps("AAA", "ZZZ", &['R', 'L']), Some(2)) + assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_steps("AAA", "ZZZ", &['R', 'L']), Some(2)); } #[test] @@ -109,7 +140,7 @@ ZZZ = (ZZZ, ZZZ)"; static NETWORK_DATA: &str = "AAA = (BBB, BBB) BBB = (AAA, ZZZ) ZZZ = (ZZZ, ZZZ)"; - assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_steps("AAA", "ZZZ", &['L', 'L', 'R']), Some(6)) + assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_steps("AAA", "ZZZ", &['L', 'L', 'R']), Some(6)); } #[test] @@ -122,6 +153,7 @@ ZZZ = (ZZZ, ZZZ)"; 22C = (22Z, 22Z) 22Z = (22B, 22B) XXX = (XXX, XXX)"; - assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_ghost_steps(&['L', 'R']), Some(6)) + assert_eq!(NETWORK_DATA.parse::().ok().unwrap().count_ghost_steps(&['L', 'R']), Some(6)); + assert_eq!(NETWORK_DATA.parse::().ok().unwrap().calculate_ghost_steps(&['L', 'R']), Some(6)); } } From 3510125b71c662b012e0d1a4cd3188d3bd8cb731 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Sun, 10 Dec 2023 21:12:51 +0100 Subject: [PATCH 087/120] Day 10, part 1: Rust and pipes don't match up Most of the time spent: figuring out how to best structure the data itself. --- day10.input | 140 ++++++++++++++++++++++++++++ src/day10.rs | 258 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 +- 3 files changed, 400 insertions(+), 2 deletions(-) create mode 100644 day10.input create mode 100644 src/day10.rs diff --git a/day10.input b/day10.input new file mode 100644 index 0000000..ea0986b --- /dev/null +++ b/day10.input @@ -0,0 +1,140 @@ +FL7-|-FJ7.J.FF-.|7.JFF|F--7LJ-F--.--|.FF77LFL..7-F|-F|--L77F7-F7FFF--7---7FFL|7FJ7|J7.FF--F|7-F-7.L|FF|.FF7-J77F7FF7FF|.FF|7F7|-F.FJJFLJJFF- +F-7.F-JF-7L7-|L-JF7--JLJJFL|.L|.L7|-7--J||.J.FL|FLL|LJL7L|-FL7.|FLJL.J7JJL7J|JL-.FJ.LJJ..||FJF--FF7|-J-FJJJ.|||J7.L|J||-|JL|-J-.LJ-7L-.|FFJJ +LFJ-LJJL-FJJ.LF7F|J.|7LJL|7.-7L-7.7.L7LLFL7|LL7LF7J|-FJFF|-7J.F-777JF7||FF7.L.F7LF77.F-7J-7..LLF7-F.7LF-J7JF--J|LF-JLLJ||FLL-JJF--L7||-FJ7-- +.L|F||7L7|.FL-|7||-7-LJ77LL7|LFJ|-J.F77.L|J7.FL--JF-7LFLJ.L.|L-LJL|7LJ-JF7JFL7J7LLF7F|LL7.7-7.L|L|JFJ.7.LF-L|L77F-7F-JL7JL7L7.|L.L|.F|.L|L-| +F---F|7F--7-JFFJ-JFL7F|F.FLL-77-|-7FFJL-7LLL-7||LL7FJJF--7|FJ|FL7JF7-JL||F-FJ|J|FL|7LJJLLF|FFFJ|-|F-7|LF7|FF-7J|7LLFJ..J-JJ-J-7|.F7FFJ-.-L-7 +LL-7J|L7.LLF7LLJ.FJ7LJ7JF|F7-LF-L.-7|LJ-JLL77L7JJ|LJ|FFJJLL7J7F--J|J.7-|L-FJ.|FLL.LLJJ.|-7JFFF-|.FJ-JJ-F-F7|JL--L-LJ|.FJJ.|.|LLJ7L|7|LL7J|-| +LF-L-F|LF7|L|7-JFFJ-JLF.|.L-7||-J7FL7||7.F--77|LF||.L-|J.F...F.|J|||---F7-F--|77L.|L--J-FJF--7F7JJJ.|JFL-J-|-F-FLF--77-F77F.F-|J7FLFL7F|LF-7 +FL-||L7LF-|JJ|LF7JJL|7.LL7|L-FJ.LJJ7|L|7.FFF7JJ||L|7.FLF7|.|.|7LF7LF7.|.F-7J|L-7JF7.|7||JFL-7|||7-|-FFJJF7J..J.L7LJL|7.||F-7-7F-F7LL.|L77|LJ +||-F7.|JL-JJ|F-|LF..|77LL-J7--|-||L77LLLL-LJJ|JF.FJF7-F|-F.F.-7-|7.L-77-|FLJFF-7-LF.|77JFJF7|||L77J.|F7-J7.F7|F.L7.-|L|L-JF|J||J|LJ|.L7.J|.J +-|-L--7.||LJ|L|.F|-L7LLF-7J.7.JFL7-JJ7..|7-|.|.L7J|FJ.F77|7.F7.7FJ77.LJFL||.FJF|JF7F|J|..FJLJ||FJ7LF-JL7|F-7LLJJJL77|-|..F||.-J.|--7.L77|L-| +|.FLF-|-7L.FF.FF|-7.F7J|LLJ.|J|F-L-7|F7FL7F|..L.|FFF7FJ|F7L|J7|LJ-7777L-|J|7|FLL-LL7-F7-FL--7||L777L--7|FJFJ7-||--|-|.F7FLJ7J..FJ--|--JF7|FJ +J-L-7FL-J.|JJ77LLJ-FF7-F.L-77.7.||7F7|L7.LLL.7.7FF7||L7LJL77|FF7L7JJF7.FF-F-77LJFJ.7F||-F-7FJLJFJL|-F7||L7L77|F7.FFFF7||-|L77F77J..F7.|L-7|J +FLL-FJJ.|.LJ-JJ---||J|..F-7||F7-J.F|||FJ777|7F7F-JLJ||L-7FJLFFJ|LJ|.F.F7L|L7|F7L|.-LFJL7L7|L--7L7F7F||||FJFJF7||F7F7|LJ|F7|||-JJL--JJ|FJ-JJ- +L7|.L7F-F|7.F..-.F|J.LF7J-F-7||.LF-JLJL-7-F7F||L-7F-JF7-||JF7L7|7.F7|F-7-F-J|||F-7.FL-7L7||F-7|FJ||FJLJLJFJ|||||||||L-7LJL-7|.LF7-J--JL-77.| +L-|FLL7.F|77L77.F7|F7.|||L7L-||7FL-7F---JFJL7|L7FJ|F7|L7||7||.|L7-F7FL7L7L-7LJL7.FF7|FJFJ||L7LJL7||L7F---JF-JLJ||LJ|F-JF7F-J7.FJL7LFL7L.LFFJ +|J|7.L|F||F77-7-|-7LL7||7F77|||F-7FJL7|F7L-7||FJ|FJ|LJFJ|L7||FJFJFJ|F7|FJF-JF--J.FJ|FJFJFJL7L--7LJ|FJ|F-77|F---JL-7|L7FJLJF77-L7F77|L|7|7JJJ +LFJ--.LLJ7FJLLFJ..F-|7||FJ|F7||L7||F7|FJ|F7|||L-JL7|F7L7|FJ||L7L7L7||LJL7L-7L--7-L7LJFJFJF-J-F7L7FJ|FJL7|FJ|FF7FF7|L7|L77FJ|JFF7JL-L7.F||FFJ +FJJ-JFL|-LJ|.L|.L-L-F7||L7LJ||L-J|||LJL7||||LJF---JLJL7LJ|FJ|FJFJFJ|L7F-JF7L7F7|F7|F7L7L7L7JFJL-J|FJL7.||L7L-JL-J|L7|L7L7|FJFFJ|FF7|7LJJ-|JJ +-LJ7.LF-.L77.F7F7F||||||.L-7|L--7|||F7FJ|||L-7L-7F-77FJF-JL7LJFJLL7|7||F7||FJ|LJ||LJL7L7L7L7|F--7LJF7L7||J|F-7F--JFJL-JFJ||F7|FJ-7-|7|F|J||7 +.L--7J|L-LL77|7||7F7|||L--7||F--JLJ||||FJ||F-JF-JL7L7L7||F7L-7L-7FJL-J||LJ|L7L7FJL7LLL7|FJFJLJF-JF7|L-J|L7|L7|L7F7L--7FJJ||||||7.L.LL-JJLF-- +..|.F7|L7J|L-L--F-|LJLJF7FJ|||F---7||LJL-J|L-7|-F7L7|FJL7||F-JF-JL-7F-J|F-JJL7LJF-JF--JLJFJF7JL-7|LJ|F7|FJL7|L-J||F77||F7|||||L-7.7-FL7|F-J7 +.F|JL||F|--7-7-LJLL-7F-J||-||LJF7FJLJF7F--JF7||FJL7||L7FJ||L7FJFF-7|L-7||F7F7|F-JF7L---7FJFJL7F7|L-7FJ|||F-JL7F7||||FJLJ||LJLJF-J7.FFJF.||F- +7FJ-7L-FJJLL-J|L-7F-J|F-JL-JL7L||L---J||F7FJ||LJF-J|L7|L7||FJ|F7L7|L7FJ|||LJ|||F7||F7JFJL7L7FJ|LJF-J|FJ||L-7FJ|LJLJ||F--J|F---JJFJ-LJFL-F7|| +FJJ|JJ||7.L|FL7.FFL7FJ|F7F--7L7|L-----JLJ||FJL-7|F7L7||FJ|||FJ|L-J|FJ|L|||F-J||||||||FJF-JFJL7L-7L7FJL7||F-JL7L-7F-J||7F7||F7F-77.7LFL7LLJ|F +|7LFFJ|F-..LJF77L|7LJ.LJLJF-JFJL--------7LJ|F7FJ|||FJ|||J|||L7L--7||FJFJ||L-7|LJ||LJ|L7L-7|F7|F-JFJ|F-J||L-7FJF7|L--JL-JLJLJLJFJJ7LFL-J..LL| +L-FJLFJLJ.L.L-LJLLF7F7F--7L-7L-7F-7-F7F7L7FJ||L7LJ|L7LJ|FJ||FJLF-J||L7L7LJF-JL-7|L-7|7|F-J||LJL-7L7|L7FJL7FJL7|LJF-7F7F7F7F--7|J|.FF7F7F7JF- +L.|-|.-.L|.F7J|7.F||||L-7|F7|F-JL7L-J|||FJ|FJ|FJF-JFJF-JL7|||F7|F7|L7L7L7FJF---J|F7|L-J|F7||F7F7L7|L7||F-JL-7||F-JF|||||||L-7LJLL-F--J-F7-|. +J7LFF--F.-7||F77-FJLJ|F7||||||-F7L--7|||L7||FJL7L7-L7L-7FJ|||||LJ||FJFJ-|L7L---7|||L7F-J||||||||FJL7|||L7F7FJLJ|F-7LJLJ|||F7L-7||-FJJ|LLL-L- +LL7|||LL7J-F-JL7FJF-7||LJ||LJL-J|F7L||||FJ||L7-|FJF7|F-JL7||LJL-7||L7|F7L7L-7JFJ||L-JL7FJ||LJ||||F-J|||FJ||L7F-JL7|F7F7LJ|||F7L7F-77FL..LF-J +||FLJ|F7|LFL--7|L-JFJ|L-7LJF--7FJ||FJLJ|L7|L7L7||FJLJL7F7|LJF---J|L7|||L7|F-JFJFJL7F-7|L7|L-7LJ|||F7||||FJL7|L7F-JLJLJL-7LJLJL-J|FJ-7F7J-JJ7 +7-F77FLF|-F7F-J|F7FJFJF7L--JF7||FJ|L--7|FJL7|FJ||L---7||||F-J-F-7|FJ||L7|||F7L7|F-JL7LJFJL-7L7FJ||||||||L7FJ|FJ|F7F7F---JF-7F7F7|L--7JLJ.J7| +-7LL7F.-F-J|L-7|||L7L7||F--7|LJ|L7|F7FJ|L-7|||FJ|F7F7|||||L7F-JFJ|L7|L-J||LJL7||L-7FJF-JF--JFJL7|||||LJL7||-|L-J|LJLJ-F7FJFJ|LJ||F7FJ--.L-77 +L-.LJJ7.L-7L--JLJL7L7|||L-7|L-7|FJ|||L7L7FJ||||FJ|||||||||FJ|F-JFJFJL--7||F--J||F-J|.L-7|F-7|F7LJLJLJF--J||FJF7FJFF7F7||L7L-JF7LJ|LJFF.|.F7| +||L-|J.F--JF-7F7F7L-JLJL--JL7L||L7||L7|FJL7|||||FJ||||LJ|||FJL77L7|F7F7|LJ|F7FJ|L-7L7F7|LJFJLJL--7F--JF-7|||FJLJF-JLJLJL-JF--JL7FJ7FLLJ.L-|J +J-JL-7-L-7FJFJ|||L7F-------7L-J|FJ|L7|||F7|||||||FJ||L7FJ|||F-JF7||||||L7FJ||L7|F7L7|||L-7|F7F7F7||7F7L7||LJL7F-JF7F-7F7F7L---7LJ.L7|.|-|||J +.L7..F-F-JL7L-JLJ|LJF-7F7F7L--7|L7|FJ||||||LJLJ|||FJL7|L7|||L7FJ||||LJ|FJ|FJL7|LJL-J|||F7|||||||LJL7|L7|LJF--J|F-JLJ-|||||F7F-J||-L-|7.LF|.F +7-|-|||L-7FJJF--7F-7L7||LJ|7F-JL-JLJ-LJ|||L--7FJ||L-7||FJ|||J||.||||F-JL7||F7|L7F---J|||LJ||LJ|L-7-LJJLJLFJF--JL7F7F7LJLJLJ||F7JLFFLJ||7FJ7L +|||.|FFJJ||FFL-7|L7|FJLJF7L7L---------7|||F--J|FJL7FJLJL7|||FJL7||LJL-7FJLJ|LJFJL7F7FJ|L-7LJF7|F7|F------JFJF7F7LJLJL7F7F7JLJ||L7J--7|J7--LJ +7-J-J-J7FLJFF--JL-JLJF--JL7L---------7|||LJLF-J||FJL---7LJ|||F7||L--7FJ|FF-JF7|F-J|||-|F-JJFJLJ||||F7F7F--JFJLJ|F-7F7LJLJL-7FJL7JFFLLJFL7.L| +L--FJ|-|7F--JF------7|F---JF7F-7F7F-7||||F--JF7L7L7F7F-J-FJ||||||F--JL7L7L-7|||L7FJLJFJL7F-JF7FJLJ||||LJF--JF77|L7LJL------J|F-JFJ-F.|7L|F-7 +L|||-JLL7L--7|F-----J|L-7F7|||FJ|LJFJ||||L7F7||FJFJ|LJF--JFJ||LJ|L---7|FJF7||||L|L7F-JF7|L7FJ||F-7||LJF7L-7FJL7|FJF77F7F-7F-JL--77J.L.-.L7.| +F--J||.L7JF7LJL--7F-7L7FJ|||LJL7|F-J7LJLJLLJ||||7L7|F7|F-7|L|L-7|F--7|||FJLJ||L7L7|L-7||L7LJFJLJFJ||F-JL--J|F-JLJL|L7|||FJ|F----JF77.|L7LJ7L +|.|L777FFF|L----7LJFJFJL-JLJF--J||F7F7-F7|F-J|||F7LJ||LJFJ|FJF-J|L-7||||L-7FJL7L7||F-J|L7|F-JF7FJL||L-7F---JL--7F7L7||LJL7||F--7-||LJJ-|.LJJ +L-77.FL|LFL----7|F-JFJF-7F7FJF--JLJLJL-JL7L7FJ|LJL--JL-7L-JL7L-7|F-JLJ|L-7|L7L|FJLJL-7L7LJL7FJ|L7FJL7FJ|F--7F-7LJL-JLJF--J|||F-JFJ|7|-F|-7|J +L|J77.||-F-7F7FJLJF7L7L7LJ|L-JF7FF----7F7L7|L7|F7F---7FJF---JF7||L---7L--JL7L7|L---7LL7L-7JLJFJFJL7FJL-JL7|LJFJF-----7L---JLJL7FJFJF7LLL-J7| +F7F7-|-7.L7LJLJF7FJ|FJ-L-7L---JL7L---7||L7||FJ||LJ7F-JL7L--7FJLJL7F--JF----JFJ|F7F7|F-JF7L7F-JFJF-J|F-7F7L--7L7L---7|L-7F-7F-7LJFJJ||-|L--77 +-J-L7J|JFF|F---J||-||F---JF7F--7|F7F-JLJF||||FJL--7L--7L-7FJ|F7F-JL--7|F7F-7|.||||||L-7|L7||F7L7|F-JL7LJL---J.L-7F7L--7LJ7LJ7L-7L--J|77-J-|7 +J.FJL-|7JFLJF---JL7LJL7F--JLJF7|||LJF---7||LJL---7L--7|F7|L7LJ|L7F7F7|||||FJL7LJ|||L-7|L7|||||FJ||F-7L---7F7JF7F||L7F7L---7F--7L7F7FJ7JLJ--7 +F-L.|JJF77J-L---7FJF-7LJF----J|||L--JF--JLJJF7-F7L---JLJ||FJF7|FJ|||LJLJ||L7FJ-FJ|L7FJL-J||LJ|L7LJL7L----J|L-JL7|L7|||F7F7LJF-JL||LJLL-77F|J +|J-|L-FJ|LF7F-7FJ|-L7|F7L----7LJL---7L-7F7FFJL-JL7-F---7||L7|||L7||L-7.FJL7||F-JFJFJL7FF7LJF7|FJLF7L------JF--7||FJLJLJ|||F7L--7||J|||||F77J +7-7FJ|L7L-J|L7|L7|F-J|||F7F-7L-7F--7L-7LJL-JF7F-7L-JF--J|L7|||L7||L-7L7L7FJLJL-7|7|F7L-JL7FJLJ|F7||FF-----7L7LLJLJ-F--7||||L7F-J||77|FFLJL7| +L-|7L--L--7L-JL-J|L-7|||||L7L--JL77L-7L-7F-7|||LL7F7L--7L-JLJ|FJ|L-7L7|.|L--7F-JL7|||F7F-JL--7||LJL7L--7F7L-JF7F7F7|F-JLJ|L7LJLFJL-7JF|-F-F7 +F7.JJFF-7F|F7F7F-JFFJLJLJL-JF--7FJF--JF-JL7LJ|L-7||L---JF7F7FJ|FJF-JJ|L7|F7FJL7F7|||||||F7F7FLJL7F7L-7LLJ|F--JLJLJLJL---7|FJF7FL7F-J-7|.-.|J +LJF.FLL7|FLJ||||F--JF-7F-7F7|F-JL7L--7L---JF7L-7||L-----JLJ||FJL7L--7|FJLJ|||F||LJLJ||LJ||||F-7JLJL-7|F7LLJF---7F7F-----JLJ-||F7LJ7J7|7F|7|J +LF.F-LFJL---J|LJL7F7L7LJ7LJLJL---J.F-JF7F--JL-7|||F7F----7FJ||F-JF7FJ|L7F-J|F-JL--7|LJF-J|||L7|F7F7FJLJL--7L--7LJ|L--77F7F-7|LJL7-F.FFF7JFL7 +LJ-JJL|F7F7F7|F7|LJ|FJF----------7FJF7|||F7F7FJLJLJ|L---7LJ7||L-7|LJFJFJL7FJL7F-7FJF--JF7LJL-JLJLJLJF7F7F7L--7L-7|F-7L7|||FJ|F--J7JLF-7J7JJ| +FL7|7JLJLJLJLJ|L---JL7L--------7FJL7|LJ|||LJ|L----7|F---JJF-J|F-JL7-L-J7-|L7FJL7||||F-7|L---------7FJLJLJL--7|F-JLJ-|FJ|||L7|L77-FF-J.|FJ.FL +|-JF-JFLF7F---JF-7F7FJF--------J|F7LJF7LJL7FL---7FJLJF7LF7L-7||F7FJLLJFL-L7|L7FJ||FJ|.LJF---------J|F-------JLJF-7F7LJJ|LJFJ|FJFF77-J-|-J7.. +L7||.F|L|LJF7F7L7LJ||L|F7F-----7LJL--J|F--JF7F7.|L7F-JL-JL77LJLJ||F7JJF.|-||-|L7LJL-JF-7L-------7F-JL----7F7LF7L7LJL7F-JF7L-JL--JL7||.|77F77 +L7-JFLFJL7FJLJL-JF-JL7LJ||F----JF----7LJF--JLJL7L-JL7F----JFF-7FJLJL-7----||7L7|F|J|LL7|F------7LJF--7F-7LJL-JL-JF--J|F-J|F7F-7F7FJ777F|7JF| +FJJL|J..LLJLF---7L---JF-J|L7F-7FJF---JF7|F-----J|F-7|L7F7F77|FJL-7F7FJ.FJ-LJFLLJJJLFF-JLJF7F7F7L-7L7FJL7|F-7F-7F7L---JL-7LJLJFJ|LJJ||-FLJ.LL +F7.-|..F|.|LL--7L----7L7FJ.||FJ|FJF--7||||F---7F7L7LJFJ|LJL-JL7F7|||L7J7-LJ-7JFJ.F7FL--7FJLJ|||F7L-JL--JLJ.LJJ|||F7F-7F-JF7F7L-JJ|FFJFJ|LFJ| +|-J||.FL-7LF7F7L----7L7||F-J|L-JL-JF7LJLJLJF--J||FJF-JF|F-7F-7LJ|LJL-J-F.FLFF7|L7JLJLF-J|LF7LJLJL--------7F--7LJ|||L7|L--J||L77--|FJ-J7|7F77 +7.LLF7J..F7||||F7F7||FJLJL--JF---7FJL7F-7F7L-77|||FJF--JL7|L7L--J.F--77F-7L||7J.|F|7LL-7|FJL7F7F7F-7F----J|F-JF7LJL-JL-7F-JL7|F7|L|JLF|JL-F- +|-FLJ|FFFJLJLJLJLJ|FJ|F7F7F7FL7F7|L-7LJ-LJL--JFJLJL-JF---JL-J.F7F7|F-J7|FLF|J.|FFL|JJF|LJ|F7LJLJLJFJL-----JL-7||F7JF7F7LJF7FJLJL--77--77J-|J +F---7L-F|F------7FJL7LJ||LJL-7LJ|||FJF7F7F7F--JF7F7F7L-7JF7F--JLJLJL7J-LJF7JFF--F-JJ-FLJ7LJL7F---7|JF7F7JF7F7|||||FJLJL7F||L7F----JJ-|LL7JL7 +L-||L7|FLJF7FF7FJL7|L7FJL--7FJF-JL7L7|||LJLJF7FJ||||L-7L-J||F----7F-J|FLJ|J.L7J.JJL7.||LF7F7||F--JL-JLJL-J|||LJLJLJF---JFJL-JL7F--7LFLJF--77 +|-F7.LL.LFJL7||L-7|F-J|F7F7|L-JF-7L-J||L7F--JLJ.LJ|L-7|F-7LJL--7JLJ|LL7.L|7-|FJL|.LL-|7F|LJ|LJL--7F7F----7||L7F---7L7F--JF-7F7LJF-JF7|FLJ.JJ +|FLJF-JF-L-7LJL--JLJF7LJLJLJF-7|FJF-7|L-JL------7FJF7|||F|F-7F7L-7.77JL7.--.FJ7F|-7|-F7FL-7L----7LJ||F---JLJ|LJ.F7L-JL7F-JF||L--JF7|L-7LL7.- +L||.|.F|J|FL----7F7FJL--7F-7L7LJL-JFJ|F---7F--7FJL7||||L7||FJ|L7FJ7|-7FF-7J7|J|FJ7|7.|L--7L-7F-7L--J|L-----7FF--JL-7|FJL-7FJL----JLJF7|7.7-. +FJF|-LLJLF-----7LJ|L7|F7LJLL-JF-7F7L-JL--7|L7J|L-7||LJ|FJLJL7|L||F77-|7--L7F--J|L7.|-L7F7L--JL7L7F-7|F-----JFJF7F-7L-JF7FJL-7F7F7F7FJLJJ7J-7 +.-|||.J7F|F---7L--JFJFJL------JFJ||F7F7F7|L7L7|F-J||F7LJ.F-7|L7|LJ|J-J|JFLJJJ..F777JJ.LJL--7F-JFJ|-LJL------JFJ|L7L-7FJ|L7F7LJLJ||LJ7-|7|7.L +|F7-|-|L|LJF7FJF---JL|F-7F7F7F7L-JLJLJLJLJFJFJ|L-7LJ|L-77L7LJFJ|F-JJL7|FFJ||F77F.||.FFFLF--J|F-JFJF---------7L7L7L-7LJFL-J|L7F-7LJJF77J-|-|. +77|F|-L.LLJ|LJFJF-7F7LJ7LJLJLJL7F-----7F-7L7|FJF7L7FJF-JF7L-7|FLJLL-7.FLJ7--7JF|.FL-FL--L---JL--J-L--------7L7L7|F-JF7F7F7|FJ|FJF-7|L7L7JF-J +L7JFJFJ7.LFJF7|LL7LJL----------J|F---7LJFJFJ||FJL-JL7|F-JL7FJL7F|L||JFL.F|F|L--J.7J-7..FF7F7F----7|F7F7F7F-J|L7|LJF-JLJLJLJ|FJL7|FJ|FJ||FL7| +7|FJF|7L-|L7|LJF7L-7F--------7F-J|F7LL--JFL-JLJF7F--JLJF7FJL--J-J-F7--.--FL|7J|7-FJF7.F-JLJ|L---7L-J||LJLJF7F7LJF-JF-7F---7LJF7LJ|FJL77-||FJ +LFJF7.FJ.L-LJF-JL-7LJF7F----7LJF7LJL---7F7-F-7J|LJF7F7FJLJLF-7F|J.|L..|JFL7FJ--F7F7|L7L---7L--7JL--7|L----JLJ|F-JF-J.|L--7L7FJL-7LJF-JF7FFJ- +LJL|JF--||FF-JF7F7L--JLJF--7||FJL-----7LJL-JFJFJF-JLJLJF7F7|FJ7F7-77FF7F--JJ7|L|||||FJF7F7L--7|F--7||F------7||F-JFF7L7F7L7|L--7|F7L--J|7J7| +F|..F77L-F7L-7|LJ|F-7F-7|F-JL-JF7F-7F7L-----J|L7|F7F7F-JLJLJL-7||7LJ7|L7JLJ|-F-J||||L7||||F7FJ|L-7LJLJF----7LJ|L---JL7|||FJ|F7FJLJ|F7F7|J.-7 +L.L-7L77L|L--J|F-J|FJ|7LJL-7F-7|LJ-LJL7FF7F7F--JLJLJLJF----7F-J||F7LFJFJ.7|F7L-7||||FS||||||L7|F-JF7F7|F---J7FJF-7F7FJLJ||JLJ|L--7LJLJLJ.7J7 +L|.J|FFJ.|F-7FJL7FJL7|F-7F7LJJLJF----7L-JLJLJF-7F7F7F7L---7LJF-JLJL7|FJJ.7-F-7FJ|||||FJLJ|||FJ|L--JLJLJL--7F7L7|7LJLJF7JLJF-7|F--J-||FJJFF.F +FL7-JJ|77LJF|L7-LJF7LJL7LJL--7F7L---7L7F7F7F7|FJ||||||F7F7L-7|F-7F-J||JF--7|FJL7LJ|||L--7LJ|L7L7F---------J||FJL-----JL---JFJ|L-7-JJF-JFL|-F +|L|.JJL7-JLFJFJF-7|L--7L----7LJL----JFLJLJLJLJL-JLJLJLJLJL7FJLJFJL7FJL7L-7LJL-7|F7LJL7F7L-7|7L7|L---7F-----JLJF7F-7F7F--7F7L7|F7L7J..JJJJL7| +JLLJJ|7||7|L7|FJFJL--7|F--7JL7F--7F7F7F----7JF7|F-------7.LJJJ.L7FJL7FJF7L-7F-JLJL--7LJL--J|F7||F7F-J|F----7F7||L7LJ|L-7|||FJ||L7|-77JLLJFF7 +.F7..LF7-|J-||L7L-7F7||L7FJF-J|F-J|LJLJF---JFJL-JF-7F7F7L-7JFF|L|L7J|||||F7|||F77F-7L-----7LJ|||||L--JL---7LJLJL7L-7|F-JLJ||.LJ|LJ7.FFJLJ--J +LF-JJJ.FF77FLJLL-7LJLJL-JL7|F-JL--JF7F-J-F7||F--7L7||LJ|F-JF-7F7L7L7||FJLJ|||FJL7L7|F--77FJF7LJLJL--------JLF7F7L--JLJ-F7.LJ7F7JLL|7.JJL.FJ| +|L-|7FLJ|L-7F7.F7L--7F7F7FJLJF7.F--JLJF--JL-JL-7L-J||F7LJF7L7||L7|FJ||L--7||LJF7L7||L-7L-JFJL---7F--7F-7F7FFJLJL--7F7F7||F7F7||-7J|F777L7JFJ +J7JF|-7FL-7||L-JL--7||LJ||F--JL7|F-7LFJF7F7F-7FJF7.LJ||JFJ|FJ||FJ|L7|L7F-J|L-7|L-J||F-JF7FJF----J|F7||FJ|L-JF--7F7LJLJLJLJLJLJL7|--JF77L7-JJ +LF7J|.LJLL||L----7FJ||F-J|L--7FJLJ7L-JFJLJ|L7LJFJL7F-JL7L7|L7LJL7|FJL7|L-7L--JL7F-J|L--JLJFJF7F-7LJ|LJL-JF7FJJFJ|L-------7F---7L-77JJL.FJF|J +F7|7JFFF7FJL-----JL7LJL-7L---JL7F77F-7L--7L7L--JF-JL--7L-JL7L--7|||F7||F7|F--7FJL-7|F7F-7|L-J||FJF-JF----JLJF7L7L7F-----7|L7F7L--J777|-|-J|. +FF----7||L-7F7F7F-7L7F7L|F---7FJ|L-J||F--J7|F7F-JF7F-7L-7F-JF--J|||||||||LJF-J|F7FJLJ|L7|F-7FJ||FJJFJF7F----JL7L-J|F--7FJL-J|L-7F7F-7F77FLL7 +-L-7F7|||F7LJ||LJLL7LJL-J|F--JL7L---7||F--7LJLJLFJLJFJF-JL-7L--7||||||LJL-7|F7LJ|L-7FJFJ||FJL-JLJF7L-J||F-----JJF7|L-7LJ-F-7|F-J|LJFJ|L77-J7 +LL.LJ|LJ||L-7LJF77.L7F-7FJL---7L----JLJ|F-JF-7F7|F--JFJF---JLF-JLJ|||L--7FJLJ|F-JF7||7L7||L7|F-7J||F7LLJL----7F7|||F7L--7L7LJL7FL-7|F|FJ---F +-.7J.L-7LJF-JF-JL7F7LJFJ|F----JF-7F----JL-7|FJ|LJ|F7FJFJF--7FJF--7|||F7FJ|F7FJL-7|||L7FJ||FJFJFJFJLJL7F------J|||LJ|L---JFJF7FJF7FJL-J|-L|F- +|F|.F-7L-7L-7L--7LJL-7L-JL-----JFJ|F------J|L7L-7||||FJFJF-JL7|F-J||||||FJ||L7F7||||FJL7|||FJFJ-L---7|L7F7LF7J|LJF-JF7-F-JFJLJFJLJF7F-J..|-J +LFFFJFJF7|F-JF77L---7|F7FF7F7F-7L-J|F7F7LF7|FJF7|LJ|||FL7L-7JLJL-7LJLJLJ|FJL7||LJ||||F-J||LJFJF7JF--JL7LJ|FJL-JF7L--JL-JF-JF77L7F-JLJ|L-|||. +|F.L7L-JLJL--JL77F7FJLJ|FJ|||L7|F-7||LJL-JLJ|FJ|L-7||L7-|F-JF7F-7L7F---7LJF-J|L7FJLJ|L-7||F-J-|L7L-7F-JF7LJF-7FJ|F7F-7F7L--JL-7|L-7J77|-|J-J +F.7.L7F7F-7F7F7|FJ|L--7|L7LJL-J|L7|LJF7F----J|FJF7|||FJFJ|F7||L7L7LJF77L-7|F7|FJL7F-JF-JLJL--7L7|F7||JFJ|F-J.LJ-LJLJFJ|L7F7F-7LJF-J|FL|-|.F| +L-F7F||||FJ|LJ|||FJF7FJL-JF-7F7L-JL-7||L-7F--J|FJ||||L7|FJ|LJL7L7|LFJ|F7FJLJLJ|F7||F7L-7F-7F-JJ|||||L7L7|L----7F---7L7L7LJLJFJF7L7F7-|J.7F|J +-7|L-J|||L7|F-JLJL-J|L---7L7||L7F7F7LJ|F7||F--J|FJ|LJFJ|L7|F--JFJ|FJFJ||L7F---J|||||L-7||FLJF7FJLJ||FJFJL-7F7FJL7F-J7L7L---7L-J|FJ|||L-|.LJF +LFL-7FJ|L7LJL7F-7F-7L----JFJLJFLJLJL-7LJ||||F7FJL7|F7L7L7LJL7F7L7|L7L-J|FJL---7||||L-7LJL7F7||L--7|||7L--7LJLJ7FJL-7F7L-7F-JF--JL-JL77JJ|7FJ +.|J|LJ.L7|F--J|FJ|FJF7F7F-JF---------JF7LJ|||||F-JLJL7|FJF--J||FJL7L-7FJ|F7F--J|||L7FJF7FJ|LJL7F-J|||F7F7L---7FJF--J|L-7|L-7L7F7F7F7L777LJ-J +F|-|-LL-LJ|F-7|L7||FJ||LJF7|F-------7FJL7.||||||F7|F7|LJFJJF7|||F-JF7||.LJ|L-7||||FJL-J||LL-7FJL-7||||||L----J|FJLF7|F-JL-7L7||||||L7|7|.LJJ +LJ|..|7FLFJ|FJ|FJ|||FJ|F-J|LJ-F7|F--JL7FJFJ||||||L-J||F-JF7|||LJL-7|LJ|F7FJF-JFJ||L7F7FJL-7FJL7F7|LJ|||L------J|LFJ||L---7L-JLJLJ|L7|L-77J|. +FFF7-L77|L7|L7|L7|LJL-J|F7L---JL-JF7F7||||FJ||||L-7FJ||F7||||L--7FJL-7||||FJF7L7||FJ||L7F-J|F-J||L-7|||F7F--7F7L7|FJ|F---JF7F-7F7|FJ|F7|JF77 +77|L7J.|7LLJJLJFJ|F----J|L7F-7F7F7||||||FJ|FJ||L7FJL7||||||||F7FJ|F7FJLJ|||FJ|FJ||L7|L7|L7FJL7FJL7FJLJ|||L-7||L7LJ|FJL----J|L7LJ|LJL||LJ.JJF +LFLJF-FL-JLLLF-JFJL---7FJFJ|FJ|||LJLJ||LJFJ|FJL7||-FJ|LJ||||LJ|L7LJ|L-7FJ||L7||-||L|L7|L7|L7F||F7||F7FJ||F7||L7|F7LJF7F7F--JFJF7|J-FJ|FL|J.F +||-||--J|LL|7L-7|F----J|-L7|L7|LJF---JL-7L7|L7FJ|L7L7L7||||L77L7L7.|F7|L7||FJ||FJ|FJFJ|FJ|FJFJLJ||||LJFJLJLJ|FJ|||F-JLJLJF7FJFJ||L-L-JJ.J-L- +7J--J|J-77|F-F7|||F7F-7|F7LJFLJF7L7F7F7FJFJ|FJ|7|FJ7L7L7||L7|F-JFJFJ|||7||||J||L7|L7L7||FJ|-L7F7|LJ|F7L--7F-JL7|||L------JLJFJL||J7FLL.F-F|L +LFLL-77.LFL7-||||LJLJFJ||L-----JL-J|||LJ.L-JL7L7|L7F-JFJ||FJ|L-7|FJFJ|L7|||L7|||||FJFJ|||FJF7|||L-7LJ|F7FJL7F7||||F7F---7F7FJ7F|L7J77FJJF|JJ +77J|.|7FFL-F-JLJL7F--JFJ|F7F7F-7F--J|L--7F---JFJ|FJL-7L7||L-JFFJ||FJL|FJLJL7||L7LJ|FJ-||||FJLJ|L--JF7||LJF7LJ||LJ|||L--7LJ|L7F-|FJJ|FL7FL|L- +LL-FJ7LJL|FJF-7F7|L7F7|JLJLJLJFJ|F--JF-7|L--7FJJLJF--JFJLJFF--JFJ||F-JL---7LJL7|7FJL-7LJLJL7F7L---7|LJ|F-J|F7|L7FJ||F-7L-7L-J7|LJJ|FF7L|LJ.| +|.F-J.FL-LL-JFJ|LJ-LJLJF7F7F7FJFJL7F7L7LJF--JL---7L--7|F-7FJF7FJFJ|L7F7F--JF--JL7|F7FJF---7LJ|F--7||F7LJF7LJ|L-J|FJ|L7|F-JF---7J.LF-JL7JL77J +|-F|-L--LL7.FJFJ7|F7FF-JLJLJLJFJF-J|L7L-7L7F-7F7FJF--JLJFJL7|LJ-L7|FJ||L--7L-7F7|||LJ-L7F7L--JL-7||LJL7FJ|F7L-7FJL7|FJ|L--JF--JF7LF-FL77FJ77 +FFLJ7.|..|F-JFJ.F-JL7L-----7F7L7L-7|FJF-JL||FJ|LJLL7F--7L-7|L-7F7||L-J|F--JF-J|LJ|L---7||L7F-7F7||L-7FJL7||L--JL7FJ|L7L7F-7L7|.|JJ.F|J|LF7J| +L-7JF77FF-JF-JL-|F7FJF7F7|FJ|L7L7FJ|L7L-7FJ|L7L-7LFJL7LL7FJL7FJ|LJ|F--JL7F7|F7|.FJF7F7|||FJ|FJ|LJ|F-JL7FJ|L---7-|L7L7L7|L7L7L----7-FJFL.L-7| +FLL-L7-F|F-J7F-7LJ|L-JLJL-JFJJ|FJL7|.|F7|L-JFJF7|FJF7L7FJL7|||L|F-JL-7F-J||LJ|L7L7|||LJ||L7|L7L7FJL--7LJLL7F-7|FJFJ7L7||FJLL7F-7FJ-L-JL|.|L7 +|7|JF7-LLJ7L77L|J.L7F7F7F-7L-7|L7FJL7||||F--JFJ||L7||FJ|F7|FJ|FJL7F--J|F7||F7L-J7|||L-7||FJ|||FJL7F--JF-7FJL7||L7L-7FJ||L7LLLJ.LJJ7.|.FF.L-J +LL|7L|.FL-7JLJ.JFF-J|LJLJFJF7|L-J|F7|||||L7F7L7LJFJ|LJ7||LJ|FJ|F7||F-7LJLJ|||F---J||F-JLJL7|FJ|F7|L---JFJ|F7|LJFJF-JL7||FJ|L|J.FJLF-7FJJFJ77 +L||7||7F|J||....LL-7L7F-7|FJLJLF-J|||LJ||FJ|L7L7FJFJF--J|F-JL7||||||FJF7F7LJ||F--7||L---7FJ|L7||LJF7F--JFJ||L7FJFJ|-LLJLJJ7-J--J..|L-JJFJLLF +7JJ|JJLJ||F-.LL7.F7L-JL7||L--7FJF7||L-7LJL7L7|FJL7L7L7F7|L7F7|||||LJ|FJ||L7FJ|L7-|||F7F-J|FJFJ||F7||L--7L7|L7||FJF7.|||LL.L7FF||F.L7LJJF7.|. +L-F|||JJF-F77.LFFJL----JLJF7FJL7|||L7FJ|F7|FJ|L7-|FJJLJ|L7||||LJ|L7FJL7||FJ||L7|FJ|||||F-JL7L7|LJLJ|F--JFJL7LJ|L-JL7-F7.|-7.|-L7|7FJJF-J|FF- +.--7FJ--7-J77-7LL--7F---7FJ||FFJ|||FJL7FJLJ|FJFJFJ|F-7FJFJ|||L-7L7||F7|||L7L-7|||FJ||||L7F7|FJL-7F-JL--7|F7L-7|F---J.|7.F7-F7F-|-7L7-7|FFJL| +|J.LLJ..7-LL7LF-L.LLJ7F-J|FJL7L-J||L-7|L--7|L7|7L-JL7LJFJFJ||F7|J||||||||-L7FJLJ|L7||LJ.LJLJL7F-J|F7F--J||L7FJ|L7J7.LF7.L-JLJ7-J|L-JJJFJJL7- +F.|..-.|.LJLJ-|J.L..F-JF-J|F-J-F7|L7L||F7FJ|FJL7F---JF7L7L7|||||FJ|||||LJF7|L-7FJFJ|L---7.F--JL-7LJ|L-7FJL7||L|FJL77J||LJ.|.LFFJFLF-J.||J.JJ +L|L77.7J7.LL7..-FJ--|F-J-FJL-7FJLJFJFJLJ||FJL7FJL7F-7|L7|JLJ|||||FJLJ||F-JLJF-JL7L7|F7F7L7L-7F7FJF-JF-JL--J||.LJJ.J7.LL7F.L.F7||LLJ.FLJJFFJ. +.|-77.|L|7..FFFLJ.FLLJFF-JF7FJL7F-JFJF-7|LJF-JL-7||FJ|FJL--7|||||L--7|||F7F7L--7L7|||||L7|F-J|LJFJF7L----7|LJ..L-F7|FF.7|F|FLJFJ-FJ-|.L.FJ-| +FJLJFLJ-|.77|-7JJ-LJJ|LL7FJLJF-JL-7L7|-||F-JF--7|||L7||F-7FJ||LJ|F7FJ|||||||F7FJJ||LJLJ7|||F7L-7L7||F--7FJ7LJ.-J-7-7-F.|F7L-J|L.F-7FL7|7F7-| +L..L-JFFJJ.-JFJJ.7.FFJJF||LJ-L--7FJ7||FJ||F7L-7LJLJL||LJFJ|FJL7||||L7LJ||||LJ|L7J|L7J.F-J||||F-J-|||L7.|L--7FL..77|.|LFJLF7|FJ|FJ7FL7LF7LJL7 +L7.|.L-JL-77.7.F-F7.J7.FLJ-L77F-J|FFLJL-J||L7FJ|-LJ.LJLFJFJL-7L7LJ|FJFF|||L7J|FJ|L-J-FL-7||||L-7-||L7|.L7F-J7LFLLJ--77|7FJ7-7.F-.|JFL-JLFJJ| +|.F77-|7.F.FF-7LJLF7F-7L|J.|LLL--JFLLJ.LFJ|J|L-7|LFJF|7L7L7-LL7|..||FJ-LJ|FJ-||-|JL7J||J||LJ|F-JFLJ-LJ-LLJJ|-.7L||JFLLJJ-LJ7LF7FF|L7-FJ-L-F| +-.FJ--FJ-||-FJL---JLL-LF|.--F7|-FLF7|.FFJFJLL7FJ--JJ|7-LL-J7LFJL-7LJ77J.LLJJF|L7L--J.|.FLJF-J|JJ|-|7LJFJJ-F.|FJ.LF---LJ.|L.|7FJ7||J.F-J-J7|J +F-L7|7JF-7.F77-77J.|.-.FL.|FLJJ.|FLJLJ-L7|JJJ|L7.LJ.FJ.LL7F7LL---JJL7-777-L|LL-J.F7||FFJ.LL-7|7LL.-||7L-J7.LJ77|J.|.||FFJJF-J--LF|7.|J7..FJ7 +L7LL-|.-JF-7JJ.LJ..7-||JLJJLLJ7F-7...L7|LJ.|FL-J-7L7...|.LFL7||LLLJF-JLJ7F.-7||L.|LJL7JF7.LJLJF77FL.-FJ7.F7LJ-|J7FJF7J|L-7-LJJ-F-L-7|JL-FJF| +J-FJFL7JJL-JL7.F-7.L.L|L--7JFF|||.|7-|J-JJF7JFJ7.--|7.FF7J|||JFF.FFLJ|-L7..LF|F77JFL7J-|-|J7FLFJ|J|-L77|7L7.LJJ|F7F|JJFLJ|LF-7-F-7|.|.J7||7. +FLJ.L-7.|L7.F77|FJ----|-JLJ-|J-F7LL7-7|..-|-77LJ7.||--LFJJJLJFLJ.LJ.FL.FF-7.LL-LJ-LJJ7.-7|-FJJ.-JJL7J|-J7|.--L.L|.7|LFL---77-|-JF--LL7FF-LJ| +|7F-J.-77-F7||.|||.7JF|.|.LJL|7.JJFJ.LJF|LL|7F7-|-|LJ...LLJ.-7F--||F-7LJJ||--7-JL-7.L--7FJJ|LJ-JF7J|LL-FF7-|F|7FL|---FJ7|L77-|..|L|JLLJJFF-L +|7LJLFJF-7L-F7.LLJ-L.LF77J7FF|-FJ.JJ-LF-F-FF-||FF-|.F7-||FFFJF|-FLJ|-LF|-7JLLF-|.FL77F|7..FL7.-7JJFL...F-7LL7.-JJLF7L..FF.L|-|--7FJJFL||LJ.| +--7F7JL|.|J.LJF7JLLF|FJL--777|||.7-J.FLL-7LJLLJ7|7L|J7L|FJJ7.LJL7JLL7||J-7J-J|L7--7J|-L-J.--7.L|-7.F7J7FL|JLJ-L7J.JJJF-L7..|-||LLJL7|7J||LF| +|J|-J-7L-J.FJ7LJ-----7J-LFJLJ-F7JJ-|---7L7--JJ--JFLJLL7-LJL..LL--7-L-|J.L|...J-L--L-LJJLJ.|.J--L-J|JJ--7LL7-J.LJ--LJ.L-LF.L-.FJJ.F-JL----.-L diff --git a/src/day10.rs b/src/day10.rs new file mode 100644 index 0000000..af19214 --- /dev/null +++ b/src/day10.rs @@ -0,0 +1,258 @@ +#[derive(Clone, Copy, Debug, PartialEq)] +enum Direction { + North = 0, + East, + South, + West, +} + +impl Direction { + pub fn opposite(&self) -> Direction { + match self { + Direction::North => Direction::South, + Direction::East => Direction::West, + Direction::South => Direction::North, + Direction::West => Direction::East, + } + } + + pub fn x_offset(&self) -> isize { + match self { + Direction::East => 1, + Direction::West => -1, + _ => 0, + } + } + + pub fn y_offset(&self) -> isize { + match self { + Direction::North => -1, + Direction::South => 1, + _ => 0, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +struct Tile { + symbol: char, + // Connections in North, East, South, West order. + connections: [bool; 4], +} + +impl Tile { + const GROUND: Tile = Tile { symbol: '.', connections: [false, false, false, false] }; + const START: Tile = Tile { symbol: 'S', connections: [true, true, true, true] }; + const VERTICAL: Tile = Tile { symbol: '|', connections: [true, false, true, false] }; + const HORIZONTAL: Tile = Tile { symbol: '-', connections: [false, true, false, true] }; + const NORTH_EAST: Tile = Tile { symbol: 'L', connections: [true, true, false, false] }; + const NORTH_WEST: Tile = Tile { symbol: 'J', connections: [true, false, false, true] }; + const SOUTH_EAST: Tile = Tile { symbol: 'F', connections: [false, true, true, false] }; + const SOUTH_WEST: Tile = Tile { symbol: '7', connections: [false, false, true, true] }; + + pub fn all() -> impl Iterator { + [Tile::GROUND, Tile::START, Tile::VERTICAL, Tile::HORIZONTAL, Tile::NORTH_EAST, Tile::NORTH_WEST, Tile::SOUTH_EAST, Tile::SOUTH_WEST].iter() + } + + // Return whether the current tile connects to the other tile in the given direction. + fn connects_with(&self, other: &Tile, direction: &Direction) -> bool { + let self_connects_to_other = self.connections[*direction as usize]; + let other_connects_to_self = other.connections[direction.opposite() as usize]; + self_connects_to_other && other_connects_to_self + } +} + +impl std::str::FromStr for Tile { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + if s.len() > 1 { + return Err("string too long") + } + if let Some(c) = s.chars().next() { + for tile in Tile::all() { + if tile.symbol == c { + return Ok(*tile) + } + } + return Err("unknown tile") + } + Err("empty string") + } +} + +struct Maze { + tiles: Vec>, + start: (usize, usize), +} + +impl Maze { + pub fn find_loop_length(&self) -> usize { + let mut result = 0; + let mut current = self.start; + let mut previous = None; + loop { + //self.print_maze(Some(current)); + + // Find a connected tile that is not going back + let mut next = None; + for (x, y, d) in self.connected_tiles(current) { + match previous { + Some((px, py)) => { + if (x, y) != (px, py) { + next = Some((x, y)); + break; + } + }, + None => { + next = Some((x, y)); + break + }, + } + } + // Walk it + previous = Some(current); + current = next.unwrap(); + result += 1; + + if current == self.start { + break; + } + } + result + } + + fn connected_tiles(&self, node: (usize, usize)) -> impl Iterator { + let (x, y) = node; + let tile = self.tiles[y][x]; + + let mut result = vec![]; + for d in [Direction::North, Direction::East, Direction::South, Direction::West].iter() { + let (dx, dy) = (d.x_offset(), d.y_offset()); + let (nx, ny) = (x as isize + dx, y as isize + dy); + if nx < 0 || nx as usize >= self.tiles[0].len() || ny < 0 || ny as usize >= self.tiles.len() { + continue + } + let other = &self.tiles[ny as usize][nx as usize]; + if tile.connects_with(other, d) { + println!("tile {:?} connects to {:?} in {:?} direction", tile.symbol, other.symbol, d); + result.push((nx as usize, ny as usize, *d)); + } + } + + result.into_iter() + } + + #[allow(dead_code)] + fn print_maze(&self, current: Option<(usize, usize)>) { + for (y, row) in self.tiles.iter().enumerate() { + print!("{:04} ", y); + for (x, tile) in row.iter().enumerate() { + if Some((x, y)) == current { + print!("*"); + } else { + print!("{}", tile.symbol); + } + } + println!(); + } + } +} + +impl std::str::FromStr for Maze { + type Err = (); + + fn from_str(s: &str) -> Result { + let mut tiles = Vec::new(); + let mut start = None; + for (y, line) in s.trim().lines().enumerate() { + let mut row = Vec::new(); + for (x, c) in line.chars().enumerate() { + let tile = c.to_string().parse::().unwrap(); + if tile == Tile::START { + start = Some((x, y)); + } + row.push(tile.to_owned()); + } + tiles.push(row); + } + Ok(Maze { tiles, start: start.unwrap() }) + } +} + +pub fn main() { + match std::fs::read_to_string("day10.input") { + Ok(input) => { + let maze = input.parse::().unwrap(); + let loop_length = maze.find_loop_length(); + println!("loop length = {:?}, farthest distance = {:?}", loop_length, loop_length / 2); + }, + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tile_connections() { + // Start connects to tiles in all directions (assuming they connect back). + // The cases below use Start as a "joker". + for d in [Direction::North, Direction::South, Direction::East, Direction::West].iter() { + assert!(Tile::START.connects_with(&Tile::START, d)); + } + // Ground connects to nothing. + for d in [Direction::North, Direction::South, Direction::East, Direction::West].iter() { + assert!(!Tile::GROUND.connects_with(&Tile::START, d)); + } + + // Vertical connects to North and South, but not East and West. + assert!(Tile::VERTICAL.connects_with(&Tile::START, &Direction::North)); + assert!(!Tile::VERTICAL.connects_with(&Tile::START, &Direction::East)); + assert!(Tile::VERTICAL.connects_with(&Tile::START, &Direction::South)); + assert!(!Tile::VERTICAL.connects_with(&Tile::START, &Direction::West)); + + // Horizontal connects to East and West, but not North and South. + assert!(!Tile::HORIZONTAL.connects_with(&Tile::START, &Direction::North)); + assert!(Tile::HORIZONTAL.connects_with(&Tile::START, &Direction::East)); + assert!(!Tile::HORIZONTAL.connects_with(&Tile::START, &Direction::South)); + assert!(Tile::HORIZONTAL.connects_with(&Tile::START, &Direction::West)); + + // Special cases, non-exhaustive. + assert!(Tile::HORIZONTAL.connects_with(&Tile::NORTH_WEST, &Direction::East), "Failed - > J"); + assert!(Tile::HORIZONTAL.connects_with(&Tile::NORTH_EAST, &Direction::West), "Failed L < -"); + assert!(Tile::HORIZONTAL.connects_with(&Tile::SOUTH_WEST, &Direction::East), "Failed - > 7"); + assert!(Tile::HORIZONTAL.connects_with(&Tile::SOUTH_EAST, &Direction::West), "Failed F < -"); + } + + #[test] + fn tile_connections_test() { + assert!(!Tile::VERTICAL.connects_with(&Tile::VERTICAL, &Direction::East), "Failed | > |"); + assert!(!Tile::VERTICAL.connects_with(&Tile::VERTICAL, &Direction::West), "Failed | < |"); + assert!(!Tile::HORIZONTAL.connects_with(&Tile::HORIZONTAL, &Direction::North), "Failed - ^ -"); + assert!(!Tile::HORIZONTAL.connects_with(&Tile::HORIZONTAL, &Direction::South), "Failed - v -"); + } + + #[test] + fn part1_example1() { + static MAZE: &str = " +-L|F7 +7S-7| +L|7|| +-L-J| +L|-JF"; + assert_eq!(MAZE.parse::().ok().unwrap().find_loop_length(), 8); + } + + #[test] + fn part1_example2() { + static MAZE: &str = " +7-F7- +.FJ|7 +SJLL7 +|F--J +LJ.LJ"; + assert_eq!(MAZE.parse::().ok().unwrap().find_loop_length(), 16); + } +} diff --git a/src/main.rs b/src/main.rs index e866b45..8adf6e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day8; +mod day10; fn main() { - day8::main() + day10::main() } From 98b91c5aeeaa1f445d89f9c1d7b4b7177e6f51bd Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 11 Dec 2023 10:21:33 +0100 Subject: [PATCH 088/120] Day 10, part 2: Theory was pretty good, and writing Rust is getting easier. --- src/day10.rs | 187 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 179 insertions(+), 8 deletions(-) diff --git a/src/day10.rs b/src/day10.rs index af19214..8aad334 100644 --- a/src/day10.rs +++ b/src/day10.rs @@ -56,10 +56,14 @@ impl Tile { // Return whether the current tile connects to the other tile in the given direction. fn connects_with(&self, other: &Tile, direction: &Direction) -> bool { - let self_connects_to_other = self.connections[*direction as usize]; - let other_connects_to_self = other.connections[direction.opposite() as usize]; + let self_connects_to_other = self.connects_direction(direction); + let other_connects_to_self = other.connects_direction(&direction.opposite()); self_connects_to_other && other_connects_to_self } + + fn connects_direction(&self, direction: &Direction) -> bool { + self.connections[*direction as usize] + } } impl std::str::FromStr for Tile { @@ -88,7 +92,11 @@ struct Maze { impl Maze { pub fn find_loop_length(&self) -> usize { - let mut result = 0; + self.find_loop().count() + } + + fn find_loop(&self) -> impl Iterator { + let mut result = vec![]; let mut current = self.start; let mut previous = None; loop { @@ -96,7 +104,7 @@ impl Maze { // Find a connected tile that is not going back let mut next = None; - for (x, y, d) in self.connected_tiles(current) { + for (x, y, _) in self.connected_tiles(current) { match previous { Some((px, py)) => { if (x, y) != (px, py) { @@ -113,13 +121,114 @@ impl Maze { // Walk it previous = Some(current); current = next.unwrap(); - result += 1; + result.push(current); if current == self.start { break; } } - result + result.into_iter() + } + + pub fn find_num_enclosed_tiles(&self) -> usize { + // Step 1: Mark the loop: Sort the loop tiles by y and x coordinate, so we can quickly look up whether a tile is in the loop. + // The start tile is a bit annoying here, replace it with what it represents by finding the two tiles that connect to it in the loop. + let start_connected_tiles = self.connected_tiles(self.start).collect::>(); + assert!(start_connected_tiles.len() == 2); + let mut start_real_tile = None; + for t in Tile::all() { + if *t == Tile::START { + continue + } + let (x1, y1, d1) = start_connected_tiles[0]; + let (x2, y2, d2) = start_connected_tiles[1]; + if t.connects_with(&self.tiles[y1][x1], &d1) && t.connects_with(&self.tiles[y2][x2], &d2) { + start_real_tile = Some(t); + break; + } + } + assert!(start_real_tile.is_some()); + + let mut marked_tiles = self.find_loop().collect::>(); + marked_tiles.sort_by(|(x1, y1), (x2, y2)| { + if y1 < y2 { + return std::cmp::Ordering::Less + } + if y1 > y2 { + return std::cmp::Ordering::Greater + } + if x1 < x2 { + return std::cmp::Ordering::Less + } + if x1 > x2 { + return std::cmp::Ordering::Greater + } + std::cmp::Ordering::Equal + }); + let mut marked_tiles_iter = marked_tiles.iter().peekable(); + + // Step 2: Scan over the whole maze, and track which tile is "outside" and "inside" the loop. + // We assume the tile at -1,y is "outside", and then by scanning line per line change our understanding + // of "outside": When crossing a `|` tile we are now "inside", and when crossing the next one we're back "outside." + let mut inside_tiles = vec![]; + + for (y, row) in self.tiles.iter().enumerate() { + // NB: We could probably keep the previous value: The loop is fully enclosed in the maze, so at the end of a line + // we must hit "outside == true". + let mut outside = true; + let mut first_on_loop_tile: Option<&Tile> = None; + for (x, mut tile) in row.iter().enumerate() { + if *tile == Tile::START { + println!("replacing start tile with {:?}", start_real_tile); + tile = start_real_tile.unwrap(); + } + if let Some((lx, ly)) = marked_tiles_iter.peek() { + if *ly == y && *lx == x { + // Tile is part of the loop, consume this tile. + marked_tiles_iter.next(); + // See whether we cross the loop boundary: + // - | is trivially crossing + // - L-*7 is crossing (L has north, 7 has south) + // - F-*J is crossing (F has south, J has north) + // We don't need to check for horizontal tiles, because we're scanning line per line, + // and we do need to look at 7/J tiles to start at pattern as we're going west to east. + if *tile == Tile::VERTICAL { + // println!("crossed the loop"); + outside = !outside; + } else if let Some(folt) = first_on_loop_tile { + // We had a previous loop tile, check whether the current tile completes or cancels the crossing. + // The next tile is expected to be _not_ on the loop anymore, or will start another crossing. + if (folt.connects_direction(&Direction::North) && tile.connects_direction(&Direction::South)) || (folt.connects_direction(&Direction::South) && tile.connects_direction(&Direction::North)) { + // println!("finished crossing the loop"); + outside = !outside; + first_on_loop_tile = None; + } else if (folt.connects_direction(&Direction::North) && tile.connects_direction(&Direction::North)) || (folt.connects_direction(&Direction::South) && tile.connects_direction(&Direction::South)) { + // println!("canceled crossing the loop"); + first_on_loop_tile = None; + } else { + // println!("still on the loop"); + } + } else if tile.connections[Direction::East as usize] { + // This cannot be a `-`, as we would have already had another first_on_loop_tile. + // println!("started crossing the loop"); + first_on_loop_tile = Some(tile); + } + } else { + // Tile is not part of the loop, count it if we're "inside" right now. + assert!(first_on_loop_tile.is_none(), "Must not have a pending crossing when leaving the loop"); + if !outside { + inside_tiles.push((x, y)); + } + } + } + // self.print_maze(Some((x, y)), Some(&inside_tiles)); + } + assert!(outside); + } + println!("Final maze:"); + self.print_maze(None, Some(&inside_tiles)); + + inside_tiles.len() } fn connected_tiles(&self, node: (usize, usize)) -> impl Iterator { @@ -135,7 +244,7 @@ impl Maze { } let other = &self.tiles[ny as usize][nx as usize]; if tile.connects_with(other, d) { - println!("tile {:?} connects to {:?} in {:?} direction", tile.symbol, other.symbol, d); + // println!("tile {:?} connects to {:?} in {:?} direction", tile.symbol, other.symbol, d); result.push((nx as usize, ny as usize, *d)); } } @@ -144,12 +253,14 @@ impl Maze { } #[allow(dead_code)] - fn print_maze(&self, current: Option<(usize, usize)>) { + fn print_maze(&self, current: Option<(usize, usize)>, inside_tiles: Option<&Vec<(usize, usize)>>) { for (y, row) in self.tiles.iter().enumerate() { print!("{:04} ", y); for (x, tile) in row.iter().enumerate() { if Some((x, y)) == current { print!("*"); + } else if inside_tiles.is_some() && inside_tiles.unwrap().contains(&(x, y)) { + print!("I"); } else { print!("{}", tile.symbol); } @@ -186,6 +297,7 @@ pub fn main() { let maze = input.parse::().unwrap(); let loop_length = maze.find_loop_length(); println!("loop length = {:?}, farthest distance = {:?}", loop_length, loop_length / 2); + println!("enclosed tiles = {:?}", maze.find_num_enclosed_tiles()); }, Err(reason) => println!("error = {}", reason) } @@ -255,4 +367,63 @@ SJLL7 LJ.LJ"; assert_eq!(MAZE.parse::().ok().unwrap().find_loop_length(), 16); } + + + #[test] + fn part2_example1() { + static MAZE: &str = "........... +.S-------7. +.|F-----7|. +.||.....||. +.||.....||. +.|L-7.F-J|. +.|..|.|..|. +.L--J.L--J. +..........."; + assert_eq!(MAZE.parse::().ok().unwrap().find_num_enclosed_tiles(), 4); + } + + #[test] + fn part2_example2() { + static MAZE: &str = ".......... +.S------7. +.|F----7|. +.||....||. +.||....||. +.|L-7F-J|. +.|..||..|. +.L--JL--J. +.........."; + assert_eq!(MAZE.parse::().ok().unwrap().find_num_enclosed_tiles(), 4); + } + + #[test] + fn part2_example3() { + static MAZE: &str = ".F----7F7F7F7F-7.... +.|F--7||||||||FJ.... +.||.FJ||||||||L7.... +FJL7L7LJLJ||LJ.L-7.. +L--J.L7...LJS7F-7L7. +....F-J..F7FJ|L7L7L7 +....L7.F7||L7|.L7L7| +.....|FJLJ|FJ|F7|.LJ +....FJL-7.||.||||... +....L---J.LJ.LJLJ..."; + assert_eq!(MAZE.parse::().ok().unwrap().find_num_enclosed_tiles(), 8); + } + + #[test] + fn part2_example4() { + static MAZE: &str = "FF7FSF7F7F7F7F7F---7 +L|LJ||||||||||||F--J +FL-7LJLJ||||||LJL-77 +F--JF--7||LJLJ7F7FJ- +L---JF-JLJ.||-FJLJJ7 +|F|F-JF---7F7-L7L|7| +|FFJF7L7F-JF7|JL---7 +7-L-JL7||F7|L7F-7F7| +L.L7LFJ|||||FJL7||LJ +L7JLJL-JLJLJL--JLJ.L"; + assert_eq!(MAZE.parse::().ok().unwrap().find_num_enclosed_tiles(), 10); + } } From 484d80bc26bfc17bf02eb5d2be72b37ee9168e8d Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 11 Dec 2023 20:36:36 +0100 Subject: [PATCH 089/120] Day 11, part 1: `for mut x in thing.iter()` is funny ... ... somehow that actually allows to modify the underlying memory, even through further indirection of tuples and `.enumerate()`. --- day11.input | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/day11.rs | 110 ++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 +- 3 files changed, 252 insertions(+), 2 deletions(-) create mode 100644 day11.input create mode 100644 src/day11.rs diff --git a/day11.input b/day11.input new file mode 100644 index 0000000..4a37aab --- /dev/null +++ b/day11.input @@ -0,0 +1,140 @@ +.........................#.........................#.....................#........#..................#............#...............#......... +............................................................................................................................................ +...................................#......................#................................................................................. +............................................................................................#..........................#.....#.............. +..#............................#..............#...................#........................................#.............................#.. +............................................................................................................................................ +................#.....#..............#.......................................#.................#.....#...................................... +........#.............................................#..................................................................#.................. +..........................................#..................#..........#...............#.........................................#......... +#................................................................................#.............................#..........................#. +............................................................................................................................................ +............#............................................................................................................................... +.......................#.....#.................#..........................#.........................................................#....... +.................................................................................................#.......................................... +...................................#................#..................................#.............................#...................... +....#.....................................................#................................................#................#............#.. +..........#......................................................................#............#............................................. +.....................................................................................................#............#..............#.......... +........................#.........................................#.....#...............................................#................... +..#............................#............................................................................................................ +..............#.........................#...................#.....................................#......#.................................. +............................................................................#......#........................................................ +...........................................................................................................................#................ +...................#.................................................................................#..............#............#.......... +..........................#.......................#........................................#.............................................#.. +...................................................................#........................................................................ +#...............#.....................#.....#.....................................#......................................................... +.................................#.........................................#...........................#.................................... +......#.........................................................................................#...........#..............#................ +..........................................................#............................................................................#.... +....................................................................................................................#..........#............ +.............#......#........................#.............................................................................................. +.......................................#............................#..................#.................................................... +.....................................................#..............................................#....................................... +..#..........................#.................................................#...............#................#........................... +.......#.......#............................................#.....................................................................#......... +.........................................#.....#....................................................................#.....#................. +.......................................................................................................#.................................... +....#...............................................#....................#.........#..............#......................................... +.............................................................................................................#.......................#...... +.....................#........#............................................................................................................. +............................................................#.....#.........................................................#............... +.............#...............................#.........#.................................#.......................#.......................... +........................................................................#......#............................................................ +............................#..........................................................................................#...................# +.#.......#..........#..................#.........................................................................................#.......... +................................#........................................................................................................... +....................................................#...........#......................#........#........................................... +......#.....#............................................................................................................................... +.........................................................#.......................#......................#.............................#..... +.........................................#.................................#.........................................#...................... +...............................................................................................................................#............ +.......................#......................................................................#............................................. +#......#......................#...............#.....#..................#...................................................#................ +................................................................................#.............................#............................. +..................#.......................#..........................................#..............#...............#............#........#. +............................................................................................................................................ +..#.............................#..............................#............................................................................ +.............................................#............#............................................................#.................... +........................................................................................................................................#... +......................................................................#..........................#.....#.....#.............................. +.............#.....#........................................................................................................................ +.....#...............................................#.....................................#.......................#........................ +...........................#....................................#..............................................................#............ +............................................................................................................................................ +............................................................................................................................................ +...................................#..........#..............#......#.................#..........................#........#...............#. +..............#......................................................................................................................#...... +..........................#.............................................#......#............................................................ +.......#...........#.........................................................................#.............................................. +................................#.................#.................................................#.....#.............#................... +.......................#................................#............................#...................................................... +............................................#....................#..................................................#....................... +............................#.............................................................#....................#............................ +...........................................................................#................................................................ +.......#.....#.......................#.....................................................................#................................ +..#......................................................................................................................................... +.....................#.........................................................#...............#............................................ +..........................................#..........#.......#........................#..................................................... +................................#...................................#...............................#.....................#.....#........... +............................................................................#...............#............................................... +.............#.............#..........#...........................................#...............................#......................... +...................................................................................................................................#.....#.. +.#.......#...............................................................................................#.................................. +.........................................#...............#............................#.......................#...............#............. +...........................................................................#............................................#................... +....................#..........#.............#.....................................................#........................................ +......#..................................................................................................................................... +#........................................................................................................................................... +....................................................................#.............#.....................#...........#....................... +..........#......................................#.............#.............#.............................................................. +..........................#.............................#..................................#...................#...............#.........#.. +...................#........................................................................................................................ +...................................#..............................#......................................................................... +#..............#.......................................................#.......#..................#........#................................ +........................................................................................................................#................... +.......#.................#......#......................................................#.....................................#.............. +........................................................#.............................................#..................................... +............................................................................#.....................................#......................... +...............................................................#...................#........#......................................#........ +..................#...............................#..................#......................................#............................... +.....................................#................................................................................#..................... +............#.......................................................................................#....................................... +...........................#..............................................................#............................................#.... +..........................................#................................#................................................................ +.............................................................#................................#.................................#........... +.....................#..............#..............................................................................#........................ +..............................#.....................#.............#...................................#..................................... +................#................................................................#.............................#..........#................. +..........#............................................................................#..................#................................. +...................................................................................................#...........................#.....#...... +............................................................................................................................................ +.....#..............................#.............#.................#....................................................................... +.............................................#...............#...........#..........................................#....................... +.......................#......#.........................#...................................................................#............... +.#........................................................................................#............#............................#....... +..................................#.............................................#................#............#............................. +..........................#.........................#....................................................................................... +.............#......#..........................#.....................................#....................#................................. +............................................................#.............#.........................................#....................... +...........................................#................................................................................................ +..........#..........................#...............................#...............................#............................#......... +............................#..................................#.........................#................................................#. +.............................................................................#...................#.......................................... +....#...............................................#.................................................................................#..... +.................#.....#.......#...............#......................................#...........................#......................... +....................................#......................................................#................................................ +........................................................#........#..............#......................................#.................... +#......#.....#........................................................................................#.....................#......#........ +...................................................#.........#..........#.......................................#........................... +.........................................................................................#.................................................. +...............................................................................................................................#............ +................................................#..........................#....................#........................................... +.........#.........................................................................#...................#.................................... +..........................#........................................#.........................................#.......#...................... +....................................................#...................................#................................................... +............................................#.................#...................................#...........................#............. +.....................#............#......................................................................................................... +.......#....................................................................#...........................#.........................#......#.. +.......................................................#.......................................................#............................ diff --git a/src/day11.rs b/src/day11.rs new file mode 100644 index 0000000..9798974 --- /dev/null +++ b/src/day11.rs @@ -0,0 +1,110 @@ +struct Chart { + rows: Vec>, + galaxies: Vec<(usize, usize)>, +} + +impl std::str::FromStr for Chart { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let mut rows = Vec::new(); + let mut galaxies = Vec::new(); + for (y, line) in s.lines().enumerate() { + let mut row = Vec::new(); + for (x, c) in line.chars().enumerate() { + if c == '#' { + galaxies.push((x, y)); + } + row.push(c) + } + rows.push(row); + } + Ok(Chart { rows, galaxies }) + } +} + +impl Chart { + fn sum_of_shortest_paths(&self) -> usize { + // Find the "expanding" rows and columns + let mut rows_with_galaxies = Vec::new(); + let mut columns_with_galaxies = Vec::new(); + for (x, y) in self.galaxies.iter() { + if !rows_with_galaxies.contains(y) { + rows_with_galaxies.push(*y); + } + if !columns_with_galaxies.contains(x) { + columns_with_galaxies.push(*x); + } + } + + let mut result = 0; + for (g1, (x1, y1)) in self.galaxies.iter().enumerate() { + for (g2, (x2, y2)) in self.galaxies.iter().enumerate().skip(g1 + 1) { + print!("{}({}, {}) -> {}({}, {}) = ", g1, x1, y1, g2, x2, y2); + + let mut rx = *x1+1..*x2; + let mut dx = (*x2 as isize) - (*x1 as isize); + if dx < 0 { + dx = -dx; + rx = x2+1..*x1; + } + let mut ry = *y1+1..*y2; + let mut dy = (*y2 as isize) - (*y1 as isize); + if dy < 0 { + dy = -dy; + ry = y2+1..*y1; + } + for x in rx { + if !columns_with_galaxies.contains(&x) { + dx += 1; + } + } + for y in ry { + if !rows_with_galaxies.contains(&y) { + dy += 1; + } + } + + println!("{}", dx + dy); + result += (dx + dy) as usize; + } + } + result + } +} + +pub fn main() { + match std::fs::read_to_string("day11.input") { + Ok(input) => { + if let Ok(chart) = input.parse::() { + println!("number of galaxies = {}", chart.galaxies.len()); + println!("sum of shortest paths = {}", chart.sum_of_shortest_paths()); + } else { + println!("cannot parse chart"); + } + }, + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example1() { + static CHART: &str = "...#...... +.......#.. +#......... +.......... +......#... +.#........ +.........# +.......... +.......#.. +#...#....."; + let chart = CHART.parse::().ok().unwrap(); + assert_eq!(chart.galaxies.len(), 9); + assert_eq!(chart.sum_of_shortest_paths(), 374); + } +} diff --git a/src/main.rs b/src/main.rs index 8adf6e2..06b3f70 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day10; +mod day11; fn main() { - day10::main() + day11::main() } From f2a96316df81fcea6136b0d5936f13f557cf4757 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 11 Dec 2023 21:23:00 +0100 Subject: [PATCH 090/120] Day 11, part 2: It helps to write the correct assertion --- src/day11.rs | 59 +++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/day11.rs b/src/day11.rs index 9798974..43a29b1 100644 --- a/src/day11.rs +++ b/src/day11.rs @@ -1,5 +1,5 @@ struct Chart { - rows: Vec>, + _rows: Vec>, galaxies: Vec<(usize, usize)>, } @@ -19,12 +19,12 @@ impl std::str::FromStr for Chart { } rows.push(row); } - Ok(Chart { rows, galaxies }) + Ok(Chart { _rows: rows, galaxies }) } } impl Chart { - fn sum_of_shortest_paths(&self) -> usize { + fn sum_of_shortest_paths(&self, expansion_factor: usize) -> usize { // Find the "expanding" rows and columns let mut rows_with_galaxies = Vec::new(); let mut columns_with_galaxies = Vec::new(); @@ -40,33 +40,31 @@ impl Chart { let mut result = 0; for (g1, (x1, y1)) in self.galaxies.iter().enumerate() { for (g2, (x2, y2)) in self.galaxies.iter().enumerate().skip(g1 + 1) { + // if g1 != 7 || g2 != 8 { + // continue; + // } print!("{}({}, {}) -> {}({}, {}) = ", g1, x1, y1, g2, x2, y2); - let mut rx = *x1+1..*x2; - let mut dx = (*x2 as isize) - (*x1 as isize); - if dx < 0 { - dx = -dx; - rx = x2+1..*x1; - } - let mut ry = *y1+1..*y2; - let mut dy = (*y2 as isize) - (*y1 as isize); - if dy < 0 { - dy = -dy; - ry = y2+1..*y1; - } + let mut d: usize = 0; + let rx = if x1 <= x2 { *x1..*x2 } else { *x2..*x1 }; + let ry = if y1 <= y2 { *y1..*y2 } else { *y2..*y1 }; for x in rx { - if !columns_with_galaxies.contains(&x) { - dx += 1; + if columns_with_galaxies.contains(&x) { + d += 1; + } else { + d += expansion_factor; } } for y in ry { - if !rows_with_galaxies.contains(&y) { - dy += 1; + if rows_with_galaxies.contains(&y) { + d += 1; + } else { + d += expansion_factor; } } - println!("{}", dx + dy); - result += (dx + dy) as usize; + println!("{}", d); + result += d; } } result @@ -78,7 +76,8 @@ pub fn main() { Ok(input) => { if let Ok(chart) = input.parse::() { println!("number of galaxies = {}", chart.galaxies.len()); - println!("sum of shortest paths = {}", chart.sum_of_shortest_paths()); + println!("sum of shortest paths = {}", chart.sum_of_shortest_paths(2)); + println!("sum of shortest paths (part 2) = {}", chart.sum_of_shortest_paths(1e6 as usize)); } else { println!("cannot parse chart"); } @@ -91,9 +90,7 @@ pub fn main() { mod tests { use super::*; - #[test] - fn part1_example1() { - static CHART: &str = "...#...... + static CHART: &str = "...#...... .......#.. #......... .......... @@ -103,8 +100,18 @@ mod tests { .......... .......#.. #...#....."; + + #[test] + fn part1_example1() { let chart = CHART.parse::().ok().unwrap(); assert_eq!(chart.galaxies.len(), 9); - assert_eq!(chart.sum_of_shortest_paths(), 374); + assert_eq!(chart.sum_of_shortest_paths(2), 374); + } + + #[test] + fn part2_example1() { + let chart = CHART.parse::().ok().unwrap(); + assert_eq!(chart.sum_of_shortest_paths(10), 1030); + assert_eq!(chart.sum_of_shortest_paths(100), 8410); } } From d38c4011f7380c9b193a40282c4ef9d0d87a5bf8 Mon Sep 17 00:00:00 2001 From: andreas Date: Sun, 17 Dec 2023 23:58:16 +0100 Subject: [PATCH 091/120] Day 12, part 1: Arranging things Rust is horribly verbose in the areas where it feels useless, while in other areas it is extremely terse to the point of not being readable. --- day12.input | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/day12.rs | 278 ++++++++++++++ src/main.rs | 4 +- 3 files changed, 1280 insertions(+), 2 deletions(-) create mode 100644 day12.input create mode 100644 src/day12.rs diff --git a/day12.input b/day12.input new file mode 100644 index 0000000..de11f59 --- /dev/null +++ b/day12.input @@ -0,0 +1,1000 @@ +##???#??#?????????#? 11,6 +???.#??#.??? 1,1,2,1 +#????#?.???????. 3,3,4 +.#?????####.?.#? 1,1,5,1 +?#?????????#?#? 3,2,1,1,1 +.?#??.?..#. 4,1 +??.??????????.? 1,1,3,1,1 +?#???..??.?????##??# 1,1,1,3,6 +#?.?#????#?#.. 2,8 +..#??????. 3,1 +?#?????#.??# 7,2 +??#?????#.?#?##???? 3,4,5,1,1 +???????#??? 6,1 +#..?#?##??????.#?#? 1,6,1,3 +???#..??#? 1,1,2 +???#?.#?#.??.?? 3,3,1 +?#???.?..# 2,1,1 +#??#?????##?.???? 4,3,1 +#?????????.??#?. 2,4,2,2 +?#?????#???#??? 2,4,3 +?.??.??#??? 2,1,2 +??#???.??##?#.? 4,5 +?.#?.#???##???.#?# 1,2,2,5,3 +????????#?#???? 2,1,6 +.??.?#?..#. 1,3,1 +.????.??.??#.#. 3,2,1,1 +??.?#??????##?#??.?? 1,13,2 +????#??.???#??. 1,2,4,1 +??#??????###?#.#? 1,1,9,2 +??#?..##???#???.?#? 1,9,2 +?#???#??#?# 5,1,1 +?#??#.????????? 1,2,1,4 +.?????#??#?#????. 1,10 +?.???#?#?#? 1,6 +????#???#????? 2,8 +#?#???????.?.?? 7,1 +??.??#????##?#?##.? 3,7 +?????#?#?.????#?#? 2,4,7 +?.????#?###?#?? 1,8 +?.??????#.????#?##.? 7,1,5 +.???#???.?? 1,3,2 +?#.?..????? 2,2 +..?????...?????? 4,3 +???#.???.??????? 1,1,1,4,1 +?###???????#?..?? 7,1 +.???????#???????#?? 1,1,10 +#??.??##?#??.## 2,6,1,2 +??#???.??#????#?? 2,8,1 +?.?#.???#?????? 1,9 +???#??##?????. 8,1 +#??#?#?????###?? 1,5,4 +?..#??????? 1,5 +###??##?...??#?# 7,5 +?#?#??#.??## 6,3 +.????.?.??# 1,1,2 +???.?.??#??#??? 1,9 +.????..#??? 1,3 +??????..?? 1,1,1 +?.????##??#? 1,8 +????##???#.. 5,3 +??#?????#???# 2,1,2,2 +#??????????#.?##?.?# 6,1,1,1,3,1 +.?#??##????. 5,1 +?????.???#??#??##? 4,8,3 +????#?#??#?? 1,4,4 +?.?#??#??..????# 1,7,1,3 +?.?.??#????.?# 1,5,1 +?#??..?.??????# 3,1,1,1,2 +?##?#???#??.???? 4,4,3 +???#?????#?????????? 13,1,1,1 +????#?.???????#? 3,2,2,5 +?.#??#.??#?????? 4,4,2,1 +.?#?#####..?.?.?. 7,1 +##????.?#????. 4,5 +????????#????????. 2,1,4,1,2 +????.??#???..? 1,1,5 +#????.?..?#? 2,1,2 +??????#???? 2,1,5 +??#??.???? 1,3,1 +?#??#??##?.????#?.? 2,7,5 +???????.??? 4,1,1 +.?##????#??? 3,4 +???.?#.?.??.. 2,2,1,2 +????.???????. 1,7 +?#?#.?#????#? 3,1,1,1 +??#?????##??.#.??? 1,6,1,3 +?????????.?###?#. 2,1,1,2,6 +?#.##????#????#.??? 2,2,1,7,1 +#??#.?????#??. 4,5 +?#??#..?????#?#??#? 2,1,1,8 +##?.?.?#?.#?????? 2,1,2,7 +.???.???....#??# 1,2,2,1 +??#??#????##?????.? 7,8 +..?????.?. 1,1 +???????#?#??????.. 1,7 +#?????????#??..?? 1,3,1,5,1 +???.??#??.. 3,2 +???.#?#????????? 1,1,1,9 +?.?#??#??.?#. 6,1 +????#?#????.#??..? 7,1,1,1,1,1 +???..#?.#???? 1,1,3,1 +??.??...??? 1,1,1 +.##??????..#? 4,3,1 +????.??.???###??. 1,1,1,1,5 +?..??????.?? 5,1 +???????#??.?. 3,4,1,1 +#????##?.??#?.? 1,3,3 +??.?#?##?#?????????? 2,13 +????#??#?##??. 1,9 +????.???#??.. 3,3 +??#?#??#?? 3,1,1 +?#?##??.????#???? 4,2,4,1 +.??#???#???#??????#? 2,13 +?.?#.?..?#??#??#???? 2,1,8 +????.?###???#.?. 1,7 +..#?????????#???? 1,2,5 +???????.?#..? 6,1 +.#???###????.? 1,6,1 +??.??###?????#???.. 6,7 +#?..#??###???.?? 2,1,7,2 +???.??#?#??#?##?? 1,12 +#???????#?????#??#?. 1,1,10,2 +.????###???.???? 10,3 +??#?.?.#??? 3,3 +?##?????.#?? 4,1,2 +??#??.??.????##? 3,1,4 +???#####??.? 7,1 +#?##??#??#.????? 8,1,3 +.#.??#.????? 1,1,1,1 +??#??.???.#? 2,1,1 +???.????????????#??? 1,10,3 +.?.##????? 1,2,2 +?.##??#???#???.?#??. 11,4 +?????#?????##????.#? 13,1,2 +.???#?.??? 4,2 +?#?#????#?.. 5,3 +.???#?????#?#? 3,3,2 +..??.???#.????.. 4,1,1 +????????????. 1,2,1,1 +??????##..?. 1,1,1,2 +?.????#????.?????? 1,1,3,1,3 +?#???##??#???#? 8,2,2 +??...???????#?# 1,2,4 +??????#????#? 7,2 +???.#..??.?#?.#???? 2,1,1,3,2,1 +?#???###?#? 1,5 +????????????? 1,1,5,2 +.?.??#?#????????#?? 1,5,8 +.????#???.#??#?#?#.? 4,8 +?#?.????.###??? 1,4,3,1 +?##.???#?????#? 2,11 +?.??###.?.?##?##?#?? 4,8 +???##????????? 1,5,1,2 +##.????#...?#? 2,2,2,2 +.?#??????.? 1,5 +..?#?????.#??#. 3,4 +?.???.????#? 2,1,2 +.????????????#?#???? 5,11 +.???#????###????#??? 12,4 +???#??.???????? 1,1,6 +#??#.?#??.????# 1,2,4,1,1 +.?.??.???#?.??#?? 5,4 +??#?#.????.? 3,1,1 +????..???##?#????#. 1,1,8,2 +?#??.????? 2,2,1 +???#?###.?#???????.# 1,5,9,1 +#????##?#??##? 1,4,5 +?#??##.???.??? 5,1,2 +.???####?????? 7,1,2 +?##?????.#.?#####??? 4,2,1,7,1 +???##...??? 3,1 +????#????#??##???? 10,6 +???#?????????? 1,10 +#?????#?#?#??????.?? 9,1,1,1,1,1 +?????#??#?. 1,4 +????#??#?? 1,1,5 +?#?###???????#??#? 1,5,8 +???#???.??????. 3,5 +?##...#?#..?. 2,3 +???#???#.?#??#?###.# 1,5,9,1 +?.##?#??#??. 1,5,1,1 +??#?#????????#??#??? 2,1,2,7,1 +????##??##?????. 10,1 +?.?????????.???? 4,1 +.???????.# 2,1,1 +.??##??##?.?? 5,3 +??????.?.??.?#?# 3,2,1,1,1 +#?.?.#??#?#??#????? 2,1,13 +??.#.??###?? 1,1,1,4 +.??####???#?## 6,5 +??.??##????????? 2,2,2,3 +..?.###?##??????? 7,1 +??????????.? 2,4,1 +?.#.?.?.??. 1,2 +????????#.?..?? 1,5,2 +??.#??#?#??#? 1,7 +?...???#??????.? 1,1,6,1,1 +#????????#???#. 3,1,1,2,3 +#????#??.??? 3,1,1,1 +#??#?#.???#?##???.?? 6,5 +?.?.?#????#????#### 1,1,2,1,3,5 +????.????????.?? 1,1,7,1 +?##?.????.???? 3,2 +.??#.???#???####??. 3,1,9 +??#.???.##? 1,1,2 +.??##??????#?.? 1,3,4 +??.?#?#???#??#? 2,1,1,3,1 +?#?#??.?.??????.#?? 5,1,5,1,1 +???.?????##??##?? 1,1,1,7,1 +..#?.??????#? 1,2,3 +????#???##???..?#?# 2,10,4 +#???#?#?.?????.#.. 7,3,1 +.##???#???. 2,4 +?.#???????#?##? 3,2,4 +?#??#????.##????? 5,2,2,2 +.#?#?#.?#?#?##???? 3,1,7,2 +????????#????.?#?? 1,2,7,2,1 +.?#####???..??? 7,1 +???????#?? 1,1,2 +??#?.????#? 4,1 +????.??????#. 1,4,1 +???????#?? 2,5 +?????#?.?.??#? 3,1,1,1 +.?...????#? 1,1,2 +?#?????.??#. 1,1,1,3 +??#?#???#??. 4,1 +?????..???. 2,2,1 +.??.?.#?.????#??#?# 1,1,10 +.????#???#?? 5,1,3 +?#??#??????????. 9,1 +#??.?????#?#???? 3,2,7 +?#.?????????#? 1,1,4,1 +.????#??#?.#. 5,1 +???????##??.# 1,1,5,1 +?##?#??.??#????#?? 6,3,4 +?##???????##? 3,1,1,4 +#??????#.?? 8,1 +#????#??????#??# 1,1,1,5,1 +?.??.#????#????. 1,1,1,7 +..?##??###?#???????. 9,4 +??.??#?.??##???? 1,3,8 +???##..?.?? 2,2 +.?#???#??######?? 1,3,7 +.????.#?#?#??. 1,6 +??##???#???#?????# 4,3,2,1,2 +??.?????????? 2,1 +????#????????.#??? 4,1,2,1,2 +?#?#???.?..?????.? 4,2,1 +.#???#.??.?#?##??? 1,3,1,6 +??????#??# 3,2,1 +?.#.??.??#?#?##? 1,1,1,1,7 +?##????##??.? 4,5 +???.?#?.?? 1,1,1 +????#.??#?.??#?#.? 1,3,1,3,1 +?????#?#?.?????#? 1,2,1,1,3 +???.??????? 2,2,2 +?#?#??.?#?#?? 5,5 +??????????##?#? 1,1,7,1 +?????#.??????? 2,3,2,2 +?#????#?#? 1,5 +?.?#????..??#?... 5,4 +..#???#??? 1,1,3 +.#?#.?#?##??????? 1,1,4,1,2 +?##?.#?#???# 3,3,1 +?????#???? 2,5 +???#???##. 1,1,3 +??##???.#.??? 6,1,1,1 +????.??..? 4,1,1 +????.???#? 2,1,4 +?#??.???.??#????? 2,2,8 +????????##??#? 1,1,5 +?????#???. 1,1,1 +##.???.##. 2,2 +?#?.???#?????.? 2,4,1 +?????..?.??##???? 5,1,3,1 +#?#?..?????#???? 1,1,6,2 +..#????#???##?.?..#? 1,1,8,1,1 +?.?..?#??#??#??. 2,6 +.???###?#??? 1,5,1 +???.?#??#??##? 1,9 +???#?????##??.??#. 12,3 +##???????#?#? 3,3,3 +???..?#?##? 3,5 +??..??.???#??.. 2,4 +???.????..???#.????. 1,3 +???##...?.???? 3,1 +??????#?.?#.??? 2,4,1,1 +???????#.#?. 1,1,2,1 +?????##????? 1,4,1 +?####.?????#? 4,2,3 +?#.#????#..? 1,1,3 +..??#??.?#?#????? 4,6 +?###????#???####?.?. 9,5,1 +?###??#???.?.?? 10,1 +?.???#?#??#?????? 1,1,2,4,1 +.???.?????? 1,3,1 +??????#????##?.#?.?. 10,3,2,1 +.??.?.?##???#???# 1,1,6,3 +??#??????#.#?.##?#?? 9,1,4 +????.?#?#???#????.#? 3,1,2,1,3,1 +?????##?????.?# 1,1,7,2 +??????.#?????#? 1,1,1,4,1 +.?#??????#.?.. 1,4 +??????.#??. 4,1,1 +?????????#?#?? 2,6 +?.#???????#?????#??? 10,1,2 +???????#??. 1,2 +?##???????.#???# 6,2,1,1,1 +.???#?##?#?????.??? 2,6,1,1,1,1 +.??????#??? 2,3 +#???????#??.?##? 1,8,4 +.#.??##??.?? 1,3,1,1 +???..#??..?? 3,1,1,2 +?????????#????#??? 2,12 +?????.###..##?? 4,3,4 +???.?????#??#??#??## 1,16 +?????#??###? 2,1,5 +##????????#??.?? 12,1 +?.??.#?#?????#?###?? 1,5,5,1 +.???.???#?#????####? 2,1,9 +..???#??????#??. 2,7 +??.#?#??#??.?.#?#.? 2,8,3,1 +??.???#???## 1,6,2 +.????.??#??.#??#. 4,4 +???.???##?? 2,1,2 +??.???#?#??.#?????#? 1,5,8 +????.??#?..????? 3,1 +???##????? 1,5 +???#??.??????#??. 5,7 +??#??..??? 3,1 +???.??#???????#??#? 2,1,3,5,1 +???#??????#???.#?? 11,2 +??.#?#?#???.#???#?? 1,3,3,3,1,1 +?#..??.???#??. 1,5 +?.?#..?#?#???#? 2,8 +#?????#.????? 2,3,1 +#?#??#???##????.? 14,1 +??????.??????#? 2,1,1,1,2 +??#???????.??? 8,1 +??.???.#??##.???##?? 1,2,1,3,1,5 +??.????#.#.?# 1,4,1,1 +?.???.??##.. 1,1,1,2 +#????????????? 3,1,4,1 +??????#?#. 1,6 +??#?#..??#????? 3,1,6 +???#???????#??????? 1,1,1,1,5,1 +??#??#?#?###..???? 11,1,1 +???#?##?##?. 2,1,2,3 +??.??#?????????##??? 1,1,1,1,1,6 +??#????##?#.? 2,5 +.?????#.????. 2,1,1,1 +.?.?.##?????####?? 1,11 +?.#?#?#.?# 3,1,1 +#??#?#?????.#? 1,8,1 +?????#.?#?#?##??.? 1,1,1,9 +?????????#???? 3,2,1,4 +?#?#.?.?.. 4,1,1 +.#.?##?????? 1,3,1 +.?#?#?#?????.? 7,1,1 +??????..??..?#????. 3,5 +#???.?.?????# 1,1,1,6 +???????#??##??????# 1,2,12 +??#???#??..?.???#? 2,4,1,1,1 +#?#?????##??##?#??# 1,14,1 +..?#???#??#?? 6,1 +.???????????. 1,3,1 +????????#??.#?.?? 8,2 +??.??..?.#.??#?.? 1,1,1,1,4 +.?#???##????. 3,4,2 +?????#????.? 5,1 +?#??#.????#??##.? 5,1,4,2 +??.#???#?#.??.??? 1,7,1,2 +?.????#?##????? 1,1,6,1,1 +.????##?#..?.?? 2,4 +?#??????#.??.?????? 2,4,1,1,1,1 +??#??#?#??.?#?#.. 7,4 +??.?#???.. 1,1,1 +???##?#?????##?##??# 10,8 +?#.##???##.??#? 1,3,2,1 +?##?#.???? 2,1,3 +.???##??#??? 1,8 +????#??.?????. 1,4,3 +.???.????.#? 1,1,1,2 +??##?#????#????#.#.# 1,10,1,1,1 +?????#?.????#??? 3,4 +?#??#??#????#?? 3,4,3 +??.??#..?? 1,1,1 +?#??#??#????.? 1,8,1 +?#??#???????## 1,4,3 +??#.???????.?.#???# 1,1,2,3,1,5 +???.???#?.??????#?#. 3,3,1,1,3 +#??#??##?#???#??# 1,1,7,1,2 +#?##.????.?? 4,2,1 +?##???.?#????#? 5,8 +.???#?##????. 1,8 +????????.? 3,1 +??.??..????.????? 2,1,2,1,2 +???#?????#..?. 4,1,1,1 +?.?##?#??#??#?? 5,6 +???????##???#??? 2,10 +#.??.#?..????? 1,2,3 +??##.#??.? 2,1,1 +?.#?#?#?.?#??#????#? 6,6,3 +?.?????????#??#?# 1,10 +?????????#? 1,5,2 +??#?..?##??#? 3,5 +??#?#???????.#.?..## 6,1,1,1,2 +.?????#?#. 1,2,1 +.?#.#.?????#? 1,1,1,5 +#??#?.?..###?????? 4,1,9 +.#?.?#?????#? 1,2,1,1 +?##????.???????.# 6,3,1 +#.?????#????#.? 1,1,1,6,1 +?..??#.???.#??.. 2,1 +????#?.##????? 3,3 +??#??#?.?????? 5,1 +.#.##.???.?#???#?.?# 1,2,1,1,6,2 +???#?##?.??????????# 7,9 +???.?#???? 3,5 +??.?#?.???.???? 2,3,1,2,1 +?##??#?#??#????.? 8,5 +#..#?#??.?.???##?? 1,3,1,1,1,5 +?????????#?#?#? 3,1,1,3,2 +.????.?.?#?.???##?. 2,3,3 +??#?#?.?????..??#?.. 4,1,2,4 +..?#?#???.????.??#. 6,1,1,1 +?##???????.? 9,1 +#?.????.#??##????? 1,2,1,7,2 +.#.?#?.?.?#.. 1,2,1,1 +??.?????.?? 1,2,1 +.#??????.?# 1,4,1 +.???????????#??.. 5,1,2,1 +?..#????.??? 4,1 +.#?#?????? 1,7 +.????????##?? 2,2 +?#????##????.? 7,1 +..?#??..??#?...?#. 2,3,2 +?#??#.#???.??.?#? 1,2,2,1,2 +??#??###.? 2,3 +???#??#???. 1,1,4 +??#?##?.?.???????#?. 5,1,1,5 +???????????..?? 2,1,1,1,1 +????.?#????##??#??? 1,2,4,2,2 +???#???#?#?.???# 1,1,6,1,2 +???.??..?????? 2,1,4 +.?????##????????? 1,7,3,1 +?#??.????#?#?#???? 3,7 +?.?#??#?#??????.??? 11,1 +?.?#.??#???# 1,1,7 +?#?????#??.. 2,3 +.?????#???????? 2,5,4 +??.?##??.#?? 1,3,2 +???##????#.?? 1,3,1,2 +#?##?.?.?????????? 1,2,3,1 +.??.????.? 2,4,1 +#.?.??.???#? 1,1,1,1 +?.#????#????.?? 6,2 +??##.????### 3,5 +?.?????#???.#.???? 1,7,1,1,1,1 +.?????????#???#?? 6,5 +.?.??#???.???? 1,1,2 +.??.????#????.?#??? 2,8,2,1 +??..???..?#.# 1,2,1,1 +.??#???#??? 3,3 +???##?????????.? 2,5,1,2,1 +???.?##?#?#????#?.?? 1,2,1,7,1 +.??.?#.?#??????..??? 1,2,2,5,1 +????#????. 2,1,1 +?#???#?.?#?.???# 2,2,3,4 +??????.????... 4,2 +.??#?????#???? 8,1 +#??????#???? 2,2,5 +?#???????.??###?..#? 3,1,1,1,4,1 +?#??#?..??.??.? 1,2,1,2,1 +#????????????# 1,2,1,6 +?#?.?????.???##??. 1,1,1,1,6 +????#??.???? 4,2 +????????#???.#?# 4,1,1,2,3 +?##??????.????.?.??? 6,1,3,1,1,1 +??#?#??#??? 5,1,1 +??##???##???#? 2,6 +.?#?#?...?#? 1,2,3 +??????#????###??? 5,7 +?..????.????.?#. 3,3,2 +???????#?? 6,1 +???.????#?. 3,1,3 +#?..???.?##? 1,1,1,4 +??#????????? 2,1,1,1 +????##????#??? 4,5 +.??#?#.??.?????????? 5,3 +...#????#???? 2,2 +#??#???#..??? 1,6,1,1 +?#??????#????.?#.??? 1,3,3,1,1,3 +????#?#?#?#??..#?.? 10,2 +#?????.?.??#?#??# 1,2,1,1,6 +????#????????????? 3,1,1,2,1,4 +#.?????#????? 1,1,2,2 +?.##?????????? 1,2,2,5 +.?#???##???. 6,2 +.#??#??????.???## 1,7,1,2 +.??.?????#??.?. 1,2,5,1 +??#??###??#.??? 2,5,1,1 +#?.#.#??????#. 1,1,8 +???????##??#?? 2,7 +???#???##?..?? 4,2,2 +?##??#??#??..????. 11,1 +???##??????#?? 1,4,1,2 +.??.???##??#??.??.? 1,1,7,1 +#?#?#?##???.???.??.? 11,1,1 +???..?###?#??#??...# 3,11,1 +?.???.????#??? 1,1,5,1 +#??.?####????#???? 3,11 +#??.???????? 1,3,1 +?#?#?#?.?.#???? 6,5 +..?#?###..#.? 6,1 +??#.???.?#? 2,3,3 +??#??????#????? 4,5,3 +??.?????##???????? 1,14 +.?.??#?..??#.? 1,3,2 +??????.????.#. 5,3,1 +.???????.??#??????? 1,1,1,10 +???..??.?#??.#?? 1,2,2,1 +??#???#????#? 1,6,3 +???#.#???.?#?#?#?## 3,1,2,9 +?##??.?#??.???..# 3,3,2,1 +????#???????#?##?# 1,1,1,2,6,1 +#.??#??????? 1,4,1,1 +##??#??#?.###?#??#?? 8,8 +?##?????????????? 7,3 +##??????#####? 5,5 +#???#??..#?#?.? 2,1,1,1,2 +.?????..????#?? 2,1,3 +.?#???##??#??. 7,2 +???#?##?.? 1,4,1 +.?.#.?????#?????#? 1,1,3,2,2 +.##??????#??????# 4,1,2,1,3 +??.?.??##?????? 1,10 +.#?#.?#?.??#?#??.?? 3,3,3,1,1 +??##?.???####. 5,6 +.??##?.#?#?#.?? 3,5 +?.?.?#??????#???#??? 3,7 +??????#????... 1,1,1,1 +?#.?#?????????.?? 1,2,1,5,1 +????###??.#??##.??? 1,5,5,3 +.?????.#?????.????? 1,1,5,4 +.??..??#?.?? 1,4,1 +?#?.?#??##?#?#.? 1,2,6 +.#..???.?.#? 1,1,1,1 +?##?????????#???#??? 4,5,2,4 +??#??#?????#?#. 1,1,4,1,1 +#?.?#???###??#??.# 2,2,8,1 +#??.??##.?????.?# 3,4,5,1 +?..#????#????????? 1,1,4,2,3 +.#?????????#.?.?? 3,4,2,1,1 +?#?#??#?.#???# 4,1,1,3 +.??????????.# 3,6,1 +???????????? 8,1 +??????#??.??#??? 5,1,4 +?????.#??.?. 2,1,3,1 +#???##??????????#?? 1,3,1,5,2 +??#.??#???? 2,1,5 +????##????????.#???? 9,1 +?????..????#? 2,5 +?#?#?.?.??#?##? 1,2,1,7 +.#?????????? 1,1,1,1 +?#???.?#..? 4,2 +.#?.#??.????..???? 2,1,1,1,1,2 +.?##??#.???#???.?#? 3,2,4,1,1 +?.?#?#???#? 4,1 +..?..??#??#???? 1,6,2 +.??#????#?#. 3,4 +??#?#.#.???????.??## 5,1,1,4,4 +??.???????# 1,1,1 +..???#?#.??.?#.?#.# 6,1,1,1,1 +?????##??#??.? 1,3,2 +?##??#?#?##?????? 11,3 +#?#???#?????.????? 1,1,4,1,1,1 +?????..??????????#? 2,2,1,1,8 +?????###???##??? 9,4 +?????#??##???.? 1,1,1,5,1 +##?.?????##?#?##. 2,1,9 +???#?..??#????#?#?. 3,8 +???#?#???#.? 6,1 +?..??#??.. 1,3 +??????#?##.#??? 1,1,4,1,1 +???????#????.????## 6,1,1,2 +???.??..#.?.??????.? 1,1,1,1,6,1 +?.???..?#??.??###. 1,1,1,2,1,3 +?.##???????#?. 6,1,1 +?????..#.?#????#? 4,1,3,3 +?.??##??##??????? 12,1 +????.?#?##???. 1,1,8 +??###????#??.?#?.?? 7,1,1,2 +###???##????? 3,4 +.?.??##?#?#???????? 1,1,4,9 +#.????###?.#. 1,7,1 +.?#??.?????? 1,1,2,1 +?#..?????? 1,4 +?#??.????#?.?.??? 2,2,2,1 +.#???#?..?? 2,1,1 +.??????#.?##?.?.#??? 4,2,2,3 +???###?#???????.?# 1,6,6,1 +.??????#..#??.#??. 1,5,3,1 +???.?????? 2,1 +????????#?#.?????##? 2,1,3,1,4 +?.?#?#?#?????.???.?? 8,1 +##.??#?#???##??????? 2,5,3,1,2 +??#?#??#???.???? 7,4 +??.??###????#?.? 1,1,8 +????#???.???#?#???? 8,1,3,1,1 +.????.??.???##?# 1,1,2,1,4 +????##??????? 1,5,1,2 +.?#..?##?#? 1,5 +??????#???#???#?? 2,9 +?#?#???#???.?????? 1,3,4,1,1,2 +..???#?..?.? 5,1 +?##??.???##?????? 4,3,2,1 +???#??#?##?.? 9,1 +.???##?#???????#? 5,9 +?#.?#?#?????????.?.? 2,4,3,2,1 +.#.??????# 1,4,2 +#???????###????? 6,4,1,1 +???#?#?..? 4,1 +??.?##.????.#?? 1,2,1,1,1 +.????#??????#?? 1,4,4 +????.?????????.? 2,7 +#??.##????##??##???? 2,2,1,3,5,1 +??#??##..???.#??##?? 2,2,1,1,6 +????.??.#.?# 3,1,1,2 +?#.?.?#?.? 1,1,1 +.?.???#?.?????..?.?? 3,4,1 +..##???.???.#? 5,2,1 +?.?#???#?#. 2,1,3 +#????#????????.# 1,1,1,7,1 +??.???##?.?.? 1,1,2,1 +?????#????#???.?#? 1,2,2,3,1 +??.??#?????? 1,3,1 +?.??#??#?.?##?# 1,3,2,3,1 +?#??.??.??.? 2,1,1,1 +#???#???..#?? 5,1,1 +.#??????????.? 4,3,1,1 +.??.?#???.??#???#?#? 1,4,4,5 +???#??????????? 6,1,1 +?????#??????#??. 1,1,5,2,1 +?##?..??????. 3,1,2 +???..?.?##.? 1,1,2,1 +?????????#? 4,1,2 +.????.#???#?? 1,1,2,2 +..??##??????.?#?.?. 6,2 +?.?.?###?.??.#?.. 1,4,2 +.##???.????????? 5,3,1 +..????..?? 4,1 +??#?...#?#????? 3,1,1,1,1 +????????????????? 3,11 +.?.??.?#??#.?????. 1,2,2,1,3,1 +#...?.##?##??.#.#? 1,1,6,1,1 +?????????#??##?? 1,3,2,3 +#??#?##???? 7,1 +.??.??????.???#? 2,2,1,1,1 +?#.#..??.?????#? 1,1,1,1,3 +#????#?.#????#.?#?? 7,6,2 +????.?#?.?? 1,2,1 +???###..???#?.#? 1,3,4,1 +.???#?.????? 3,1 +???????#?### 3,1,1,3 +????.????.#? 1,3,1 +??????????.????#??? 1,2,1,2,1,1 +????#.??###?#?###?# 1,2,13 +##?.???#??? 2,4,1 +?#..#???#?#??? 1,1,6 +#?..??.??????????#?# 2,1,1,1,7,1 +?????.?#.????. 2,2,3 +?????.#.???#? 2,1,3 +??????#??.??? 1,1,3,3 +#??#??.?##??#??#?. 1,2,1,6,1 +#?##?.#???????#?.? 1,3,3,2,2,1 +???.?????###?#???? 1,4,8 +.?#????#???????? 4,3,1,1,1 +??.?????????????##? 1,5,1,8 +???.?#?????#?# 2,4,3 +??.????#.#?? 2,2,1,3 +??????.??????.#?#? 5,2,3 +??????????? 1,2,3 +?.?#??#???#?????## 4,8 +..##?.???#?.#??### 3,5,6 +????#??.#??.#??? 6,1,1,1,2 +?.????#???? 1,6 +????#???????#?#? 1,1,1,7 +????????.?.#?. 1,1 +.????##????.??.?? 1,6,2,1 +?##?.?#?#?.? 2,5 +??#?#????#?..#?#? 1,1,1,5,4 +###???.???.???#?? 4,4 +.??????.?##????? 2,1,3,2 +?.?????.?# 1,1,1 +#.##???????? 1,3,1,1 +#????#.?.#??????? 1,2,1,5 +.??.?##??.?.?? 4,1 +##?#.?.?###???#?#?? 2,1,1,10 +????#?.???#?.?. 1,2,1,2 +?????????????? 3,1,2 +?.#??.##?##?..#? 3,6,2 +?#.??#???#? 1,1,2 +#???????#??? 1,1,3,3 +??##??.#?#.???. 3,3,1 +#.??##???#?#???.#? 1,13,1 +?????#.??.#?? 1,1,2,1 +??#?##????????? 1,1,4,1,3 +?.???.????.?#? 1,1,3,2 +..????.?#?????.? 1,1,6,1 +?.?.??#?###?#. 1,1,1,7 +#?#.?????#????.#. 1,1,7,1,1 +???.??##????#?#? 3,3,1,3 +?.??????#??#????.#? 10,1,1,1 +??????????#???# 1,2,2,5 +?###?.#?????#?. 4,3,3 +.##???.???. 3,2 +#?#.?.????? 3,1,1 +????#???.#??? 5,1 +.?#?????#?????.??? 1,1,6,2 +#?#??##????????.?? 10,1 +???.?#???#? 1,2,1 +??#?.????????? 4,4,3 +??#?#?.##.?# 3,2,2 +?#?????.#???#.#? 1,3,1,2,1 +?????#??##..?#? 5,3 +???#.?#??? 4,4 +...??.????#????.? 1,7 +??????.?????#?????#? 2,3,6,2 +??#??.#??##??#.? 1,1,3,1,1 +.?????.??#.????? 5,1,1,2,1 +#?#????##???.#????. 4,3,1,1 +#.#???.#????#?##?# 1,1,1,2,1,6 +#?????##????#?##?.?? 10,4,1 +?#????#?#.??.##???.. 3,5,4 +?.????.?##??#...? 1,2,2 +?.???#??#?.?#??? 6,2,1 +??.?????????##?? 1,2,6 +?.?#???.#?#?? 2,2,3,1 +???..?#?#?????#?### 1,1,3,7 +?#??.?.????#????? 2,6,1 +????#?????? 2,2 +??.??#??????.?.??? 1,9,1,2 +?#???#??.?##????? 1,3,1,8 +??##?????#?..#???#.? 8,5,1 +?.???#?#???#????? 1,1,5,4,1 +.##??#??????????? 3,1,7 +??###?##???????.?.# 10,1,1 +#?#????##?????#? 12,2 +?#??#?.?#??.. 5,4 +?#?#??????#??.???.# 1,1,4,1,1,1 +?????????###.#??#??? 2,1,6,1,1,1 +???#????.?#.??? 2,2,2,1 +.??????.?????.. 4,5 +???####???.????.?.?. 7,1,3,1 +.##??#?.???. 2,2,3 +?#.?????????? 1,1,3,1 +.#?.????#??????#?? 1,5,2,1,1 +#???..?####?..# 4,5,1 +..???.???.?#.?.. 1,1 +???.#??###? 1,6 +..??.?????? 1,2 +??###??#????. 1,6,1 +#????#???.???? 2,6,3 +??#???.??????#?.#? 6,2,3,1 +.??#??????? 1,3,1 +?.?.??##???? 1,2,1,1 +...?.??#?#. 1,4 +?????#??#???????? 3,2,5,1 +??.?????.?????? 1,2,1,2,1 +???.?.??.?#. 1,1,1,1 +.?##?#???..#???.. 5,4 +??####??.????. 7,4 +#????#????#???? 9,1,1 +?.?.???.?????.???? 1,1,2,4,3 +??#?#?..??????? 6,1,3 +..?.#?#?##????#. 9,1 +?.?..?#?#.? 1,2,1 +????##?.??# 2,3,2 +?..??????##?#? 4,4 +??????????????# 1,8,1 +????#???#?????.?.?? 1,2,1,4,1,2 +?.###?#??.??#?#?. 7,4 +?.#??#?.???#???#?? 4,8 +??????##????#?..?# 1,9,1 +.?.???#????????#??? 1,2,5,2,1 +?#.???#???. 1,5 +?????#?#???#???##? 3,3,2,3 +..??????.?#? 4,1 +#.?????#??????#???#? 1,15 +?##??#??#???????#.?? 3,5,1,1,2,1 +??????..#?? 2,1 +????#.??????.#.?. 3,1,1,2,1 +.???.????? 1,2 +????.????. 1,2 +#????.#.??#??.??? 1,3,1,5,1 +#.??##???.?.?#????? 1,6,1,2,1,2 +??.?#.????.#???.#??? 1,1,2,1,1,4 +?.#?#..?#?. 1,1,2 +??#?????.?#.?.?.?.. 7,1,1,1,1 +?#?.????.??.???#.? 2,3,1,1,1,1 +???#???#.??#??#.? 3,3,1,1,1 +#????????###???#? 2,1,6,3 +??.#????#? 1,3,2 +???#??.#??##?# 5,2,2,1 +?#??????????#?? 2,5,4 +#.?#??????#?#??#?##? 1,1,14 +.??????????#????? 5,1,4,1,1 +???..?#???#??????##? 1,1,15 +#??.?#.#??????##. 1,1,1,1,4 +?????.???.?.?..#.??. 1,1 +???...#?.????? 1,2,1,3 +.????#??.?#??## 1,3,2,2 +?##?.#?..???? 2,2,1,1 +????.?.?.??? 2,1,1 +?????..???.?#???? 1,2,4 +???##.???#??? 5,3,2 +.????.???.?????? 4,2,1 +?..???#?????##?# 1,1,1,7 +###?#???#?.?#????#. 9,2,2 +???.?????. 1,1,1 +#?.?.#??#?#??# 1,9 +.?#???.?.?????? 3,5 +?.??#?..#?##???#?##? 1,2,12 +#.??#?#???#?#???? 1,12 +???.?.???##?? 1,1,4 +?.?#??#??##??# 1,2,6,1 +.????????..?????? 6,4 +???#???????. 3,2 +?.?????.???????? 2,3 +.??#.??#????#??. 1,1,5,1,1 +??.??#?###??????.?#? 1,8,4,3 +#???.?##?#?.?....?? 1,2,5,1,1 +?#???#?#?? 2,2,2 +.???##?.#?#???# 4,1,5 +?#?#..???? 1,1,4 +????????.#????#.? 3,1,1,6,1 +..?.????#??#??????? 1,1,6,1,3 +?.????###?#?. 1,6 +???..??#?. 1,3 +?#???#???????#?? 8,1,2 +?#???#???? 2,2,3 +?#????#.?# 2,3,1 +#???..??.?##? 3,2,3 +?????????##?#?#. 3,7 +?????##??.? 1,4 +#????.???? 2,1,1 +???????#???? 1,1,2,1 +??##??#??.????#??.# 7,2,2,1 +#????#??#?????? 3,1,3,2 +???#???.?.??. 2,1,1,1 +#??#????#?##??.?.? 1,10,1 +?.?.?#?.?? 1,1,1 +?..##?#.?##?????.? 1,4,5,1,1 +???#..????#????#??? 2,1,5,1,3 +??????#.???##?#????? 1,6 +????????.? 1,5 +?.??????.?? 1,2,1 +?????????.?#?#???#?? 3,10 +??????????.????? 1,1,2,2,1 +?#?#???.??.#? 2,4,1,1 +??.#?.##?? 1,2,2 +???.??#??#???.#?#? 1,1,1,3,4 +??#??##?#???.?#??? 8,3 +??##?..#????.?.? 4,1,2,1 +?.??.???????.???. 2,1,1,1,3 +????#?#????????# 1,2,3,1,4 +??..#??.??????##.?# 2,1,1,7,1 +.?????###?#?##???#? 1,8,1,1 +??#?.#???.#?? 3,1,1,2 +??#.???#????? 1,1,2,5 +?#.????.???? 1,3,2 +#???????#?.?##?? 3,3,1,5 +?#????#?#?#??#?.?? 1,4,4,1 +???#?#???.??? 2,3,1,2 +???.##???..??? 1,2,2 +#????##??.?.??.# 1,7,1,1,1 +#?##????.??.???# 5,1,1,1,2 +#???#???.??.#?? 1,1,3,1,1 +??#??????.#??.?. 6,3 +.#???.??..#?#?# 1,2,1,1,1 +.???.???#??#? 1,2,1,1 +??.??????#?#?#..??? 2,1,1,4,1,3 +?.#?##????..?????? 1,2,2,4 +#????.???.?# 1,1,1,1 +?##???????##???#?? 6,9 +.??????..?. 1,2,1 +?..#???##?###??. 1,2,7,1 +?#????##????.?#???# 2,1,2,1,1,6 +??.???#??.?.? 2,5,1,1 +.##?.#?#?? 3,5 +?#?.??##???##??????? 1,1,4,8 +.??.#????????.?# 1,4,1,1,2 +??#?..####?.. 3,5 +#?#?.?#?##?#.??#? 4,4,1,3 +????##?#???#?.##??? 1,5,1,1,2,1 +#?#????##???#??# 3,4,2,2 +?.##????#..?? 7,1 +.?????#.## 5,2 +?#.#?????????.? 2,1,1,3,1 +.???##?#?#??#??#?# 7,6 +??#???#??#???#???? 6,2,5 +?#?.???????#???###?? 2,3,3,4,1 +???.???.??#???#??? 1,1,4,3 +?##.???#?????#.#?.?? 3,2,4,1,2 +#?????.?####?..?. 3,6 +?#????..#??????#???? 2,2,1,9 +??????#?#?? 4,5 +???#?????????#???# 3,10,1 +???..?#?#.. 1,3 +???..?????#?###??. 2,9 +.???.???.? 1,3 +????#.???###.???? 1,1,3,1 +?##??????#. 6,1 +.#?#?#.???.?.?? 3,1,2,1 +.?#?.???###?#?##?#?? 2,14 +#?.???????? 2,6 +??#?###?????????#??. 8,3,3 +????.????.??#?. 3,2,1,1 +.#?#?#?#???#??##?? 1,1,5,7 +.##?#?????#?#.?.#?. 8,1,1,1,1 +????..#??? 2,2 +??????#????? 2,4,2 +?#??#???#?...? 5,2,1 +???.?.?????.? 2,5 +???#?#?##??????#.?#. 10,1,1,1,2 +#?..?.??#??????# 2,5,2 +#?????#?#??.?# 11,1 +?.#?#?.?.? 3,1 +?????.?.?#???? 3,6 +.??????#?#?? 1,1,2,2 +#??##????#?.??????? 6,2,1,4 +?.??###?.??# 1,3,3 +??????#??.?#???##. 1,4,6 +?????..??????#?#? 5,10 +?###?#?#????#?.???.? 8,3,1 +..?###??????????. 4,1,3 +??????.#?#?? 1,4 +???????#?.??? 1,3,2 +???####???.???#.? 7,1,3,1 +??#?.??.???##.??. 1,2,2,5,2 +#?.???##???.?? 1,1,6,1 +????#??????#?#?? 1,1,5,3 +.??#.?.##?????.? 1,7,1 +.?.?##??#? 3,1 +?.???????#??# 1,10 +?.???#??#??#??? 1,1,2,5,1 +?#.???#??. 1,4 +?????#?????##???? 1,5,2,1 +.#?#????##? 6,2 +#????#?##?..?? 1,3,3,1 +?#??#?..??##?? 5,4 +?.?.?#???? 1,1,1 +??#???#?##?? 6,4 +??.??.?????#??#?#?#? 1,1,1,5,6 +.????????? 1,1,4 +?#?..?#... 1,2 +?#.?#?.???.???? 1,3,2,2 +??#?#?#.???#??? 6,2,4 +????#???##? 4,4 +??.??###??#?#????#.? 11,2 +??????????.??#.???? 1,5,1,1,1,2 +?????????##?.? 1,2,6 +?????##????#.#????? 6,3,1,1,1 +?#???????#??.? 5,2,1 +??#?????????. 4,1,2 +#????.##????## 1,1,3,3 +?#?##???##???#.?? 5,4,2,2 +.#??#?#..? 6,1 +#???????##???#?.??? 1,9,1,1 +?.???...??? 1,1 +??#??.#??#? 4,4 +??.#???#.?#????? 1,3,1,1,1 +?#?.#?#.#?.?###???## 2,3,1,9 +??#?#????#??#? 7,2,2 +#??#?.?#?.??? 1,1,2,2 +..#.?.?#??.? 1,2 +????#?????#?#??? 1,1,1,6,1 +?.???##???????##?.?. 6,2 +.##.??????#? 2,7 +?.#?....?#? 2,2 +??????..?#####????? 1,3,8 +?.?????#???? 1,3 +??#???????? 1,1,3 +.???#?????.#?. 1,4,2 +?.??.#??#?#??? 1,8 +???????????????? 1,4,1,1,1 +???##?#????# 1,5,3 +??#??.???##? 1,1,1,5 +.##??#?.?????.???#? 5,2,1,1,1 +..?##.???????.?#?. 3,3,1,3 +#??#???.???#..?? 4,1,3,1 +??#????????.? 3,1,1 +??.??#???#??#?????.# 1,4,5,2,1 +?#?..????#??? 2,1,1,3 +?????...#.? 1,1,1 +??.?.??###?.?? 1,4,1 +??..?.#????#????#.?? 2,6 +.???#?????#. 7,1 +??????#?#?.#.??.??? 9,1,2,2 \ No newline at end of file diff --git a/src/day12.rs b/src/day12.rs new file mode 100644 index 0000000..7b7bda0 --- /dev/null +++ b/src/day12.rs @@ -0,0 +1,278 @@ +use std::{str::FromStr, fmt::Display}; + +#[derive(Clone, Copy, Debug, PartialEq)] +enum Condition { + Operational = '.' as isize, + Damaged = '#' as isize, + Unknown = '?' as isize, +} + +impl From for Condition { + fn from(value: char) -> Self { + match value { + '.' => Self::Operational, + '#' => Self::Damaged, + '?' => Self::Unknown, + _ => panic!("unexpected input character"), + } + } +} + +impl Display for Condition { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Ok(s) = std::str::from_utf8(&[*self as u8]) { + f.write_str(s) + } else { + panic!("I don't understand the type it wants") + } + } +} + +struct ConditionRecord { + conditions: Vec, + damaged_spring_groups: Vec, +} + +impl ConditionRecord { + #[cfg(test)] + pub fn new(conditions: &[Condition], damaged_spring_groups: &[usize]) -> ConditionRecord { + ConditionRecord { + conditions: conditions.to_vec(), + damaged_spring_groups: damaged_spring_groups.to_vec(), + } + } + + pub fn num_arrangements(&self) -> usize { + // Stupid logic: Each '?' can be either '.' or '#'. So, try both, and then proceed + // and see if _at the end_. Essentially we're building a matching automaton here?????!?!?!! + // Each state is the conditions we found. + let states: &mut Vec> = &mut vec![]; + + // Start out with one empty state: + let initial_state = vec![]; + states.push(initial_state); + for c in &self.conditions { + // println!("{:?} with states {}", c, states.iter().map(|s| Self::format_state(s)).collect::>().join(",")); + + // Modify the states depending on the condition + // If we see a '.' or '#' then it will be added immediately to the states, which may + // make some switch from "could work" to "invalid". + // If we see a '?' we fork the state, and keep the the valid parts. + let next_states: Vec<_> = states.iter().flat_map(|s| { + // println!(" ... looking at {}{}", Self::format_state(s), *c as u8 as char); + match c { + Condition::Unknown => { + let mut tmp = vec![]; + let mut s1 = s.clone(); + s1.push(Condition::Damaged); + if self.violates_constraints(&s1, true) { + // println!(" ... {:?} violates constraints", Self::format_state(&s1)); + } else { + // println!(" ... {:?} is acceptable", Self::format_state(&s1)); + tmp.push(s1); + } + + let mut s2 = s.clone(); + s2.push(Condition::Operational); + if self.violates_constraints(&s2, true) { + // println!(" ... {:?} violates constraints", Self::format_state(&s2)); + } else { + // println!(" ... {:?} is acceptable", Self::format_state(&s2)); + tmp.push(s2); + } + tmp + }, + _ => { + let mut s1 = s.clone(); + s1.push(*c); + if self.violates_constraints(&s1, true) { + // println!(" ... {:?} violates constraints", Self::format_state(&s1)); + vec![] + } else { + vec![s1] + } + } + } + }).collect(); + // println!(" ... next_states = {}", next_states.iter().map(|s| self.format_state(s)).collect::>().join(",")); + if next_states.is_empty() { + println!("no more states, can return 0 early"); + return 0; + } + *states = next_states; + } + + states.iter().filter(|s| { + let ok = !self.violates_constraints(s, false); + if ok { + println!("{}", Self::format_state(s)); + } + ok + }).count() + } + + // Check whether the given conditions violates the constraints given by the `damaged_spring_groups` + // configuration. + // If `partial` is true then the check accepts conditions that are incomplete and could be completed + // to a full valid configuration, if it is false then the conditions must match perfectly. + fn violates_constraints(&self, conditions: &[Condition], partial: bool) -> bool { + let mut next_spring_group = self.damaged_spring_groups.iter(); + let mut damaged_count = 0; + for c in conditions { + if *c == Condition::Operational { + if damaged_count > 0 { + match next_spring_group.next() { + Some(expected_damaged_count) => { + if *expected_damaged_count != damaged_count { + return true; + } + }, + None => { + return true; + }, + } + damaged_count = 0; + } + } else if *c == Condition::Damaged { + damaged_count += 1; + } else { + panic!("unexpected condition {:?}", c) + } + } + + // We're only checking whether the given conditions could still pass, so at this point + // we only want "close enough": If we collected some damaged springs, then the next value + // in the iteration must not be smaller than that. + // For a "full" check we would also verify that there is nothing left over at the end, and + // any collected damamged springs would have to match exactly. + match next_spring_group.next() { + Some(expected_damaged_count) => { + if partial { + damaged_count > *expected_damaged_count + } else { + damaged_count != *expected_damaged_count || next_spring_group.next().is_some() + } + } + None => { + damaged_count > 0 + } + } + } + + fn format_state(state: &[Condition]) -> String { + std::str::from_utf8(&state.iter().map(|c| *c as u8).collect::>()).unwrap().to_string() + } + + fn parse_state(s: &str) -> Vec { + s.chars().map(Condition::from).collect() + } +} + +impl std::str::FromStr for ConditionRecord { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + if let Some((p, g)) = s.split_once(' ') { + println!("from_str: p='{}', g='{}'", p, g); + if let Ok(damaged_spring_groups) = g.split(',').map(usize::from_str).collect::, _>>() { + Ok(ConditionRecord { + conditions: ConditionRecord::parse_state(p), + damaged_spring_groups, + }) + } else { + Err("cannot parse damaged spring groups") + } + } else { + Err("Expected two space-separated parts") + } + } +} + +fn num_arrangements(input: &str) -> usize { + input.split('\n').map(ConditionRecord::from_str).map(|cr| cr.unwrap().num_arrangements()).sum() +} + +pub fn main() { + match std::fs::read_to_string("day12.input") { + Ok(input) => { + println!("num_arrangements = {}", num_arrangements(&input)); + }, + Err(reason) => println!("error = {}", reason) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + static FULLY_KNOWN_CONDITION_RECORDS: &str = "#.#.### 1,1,3 +.#...#....###. 1,1,3 +.#.###.#.###### 1,3,1,6 +####.#...#... 4,1,1 +#....######..#####. 1,6,5 +.###.##....# 3,2,1"; + + static DATA: &str = "???.### 1,1,3 +.??..??...?##. 1,1,3 +?#?#?#?#?#?#?#? 1,3,1,6 +????.#...#... 4,1,1 +????.######..#####. 1,6,5 +?###???????? 3,2,1"; + + #[test] + fn condition_record_parse_examples() { + for line in FULLY_KNOWN_CONDITION_RECORDS.split('\n') { + if let Err(reason) = line.parse::() { + panic!("{}: {}", line, reason) + } + } + for line in DATA.split('\n') { + if let Err(reason) = line.parse::() { + panic!("{}: {}", line, reason) + } + } + } + + #[test] + fn condition_record_violates_constraints_partial() { + assert!(!ConditionRecord::new(&[], &[]).violates_constraints(&[], true), "empty allows empty"); + assert!(!ConditionRecord::new(&[], &[1]).violates_constraints(&[], true), "non-empty allows empty"); + assert!(!ConditionRecord::new(&[], &[1]).violates_constraints(&[Condition::Damaged], true), "must match single"); + assert!(!ConditionRecord::new(&[], &[2,1]).violates_constraints(&[Condition::Damaged, Condition::Damaged, Condition::Operational, Condition::Damaged], true), "must match multiple with operational in the middle"); + assert!(!ConditionRecord::new(&[], &[2,2]).violates_constraints(&[Condition::Damaged, Condition::Damaged, Condition::Operational, Condition::Damaged], true), "last can be incomplete"); + } + + #[test] + fn condition_record_violates_constraints_partial_small() { + assert!(ConditionRecord::new(&[], &[3,2,1]).violates_constraints(&[ + Condition::Operational, + Condition::Damaged, + Condition::Damaged, + Condition::Damaged, + Condition::Operational, + Condition::Damaged, + Condition::Operational, + ], false)); + } + + #[test] + fn example1_small() { + assert_eq!("?###???????? 3,2,1".parse::().unwrap().num_arrangements(), 10); + } + + #[test] + fn example1() { + assert_eq!("???.### 1,1,3".parse::().unwrap().num_arrangements(), 1); + assert_eq!(".??..??...?##. 1,1,3".parse::().unwrap().num_arrangements(), 4); + assert_eq!("?#?#?#?#?#?#?#? 1,3,1,6".parse::().unwrap().num_arrangements(), 1); + assert_eq!("????.#...#... 4,1,1".parse::().unwrap().num_arrangements(), 1); + assert_eq!("????.######..#####. 1,6,5".parse::().unwrap().num_arrangements(), 4); + + assert_eq!(num_arrangements(DATA), 21) + } + + #[test] + fn part1_tests() { + assert_eq!("???.#??#.??? 1,1,2,1".parse::().unwrap().num_arrangements(), 10); + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 06b3f70..04376eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day11; +mod day12; fn main() { - day11::main() + day12::main() } From ba11952b8dbdbcd44051aa21541cc56c6d0b2c5b Mon Sep 17 00:00:00 2001 From: andreas Date: Mon, 18 Dec 2023 00:14:36 +0100 Subject: [PATCH 092/120] WIP: Day 12, part 2: Brute force? --- src/day12.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index 7b7bda0..6e41897 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -104,9 +104,9 @@ impl ConditionRecord { states.iter().filter(|s| { let ok = !self.violates_constraints(s, false); - if ok { - println!("{}", Self::format_state(s)); - } + // if ok { + // println!("{}", Self::format_state(s)); + // } ok }).count() } @@ -192,10 +192,26 @@ fn num_arrangements(input: &str) -> usize { input.split('\n').map(ConditionRecord::from_str).map(|cr| cr.unwrap().num_arrangements()).sum() } +// See https://stackoverflow.com/a/66482767/196315 +fn repeat_element(it: impl Iterator, cnt: usize) -> impl Iterator { + it.flat_map(move |n| std::iter::repeat(n).take(cnt)) +} + pub fn main() { match std::fs::read_to_string("day12.input") { Ok(input) => { println!("num_arrangements = {}", num_arrangements(&input)); + let num_arrangements_part2: usize = input.split('\n').filter_map(|i| { + if let Some((p, g)) = i.split_once(' ') { + format!("{} {}", + p.repeat(5), + repeat_element(std::iter::once(g), 5).collect::>().join(","), + ).parse::().ok() + } else { + None + } + }).map(|cr| cr.num_arrangements()).sum(); + println!("num_arrangements (part 2) = {}", num_arrangements_part2); }, Err(reason) => println!("error = {}", reason) } From fcbb8f0b870b127d2c647c8645bedcd0613c2c70 Mon Sep 17 00:00:00 2001 From: andreas Date: Mon, 18 Dec 2023 00:20:48 +0100 Subject: [PATCH 093/120] Separate inputs with ? --- src/day12.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/day12.rs b/src/day12.rs index 6e41897..8fe5786 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -204,7 +204,7 @@ pub fn main() { let num_arrangements_part2: usize = input.split('\n').filter_map(|i| { if let Some((p, g)) = i.split_once(' ') { format!("{} {}", - p.repeat(5), + repeat_element(std::iter::once(p), 5).collect::>().join("?"), repeat_element(std::iter::once(g), 5).collect::>().join(","), ).parse::().ok() } else { From 802eaf1e709a14c7e5e0d90170374284862db3f7 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 18 Dec 2023 10:40:20 +0100 Subject: [PATCH 094/120] Skip unneeded constraint checks when '.' follows '.' --- src/day12.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index 8fe5786..d1d162f 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -58,6 +58,8 @@ impl ConditionRecord { // If we see a '.' or '#' then it will be added immediately to the states, which may // make some switch from "could work" to "invalid". // If we see a '?' we fork the state, and keep the the valid parts. + // Adding a '.' after a '.' will not actually change anything, so we can skip + // the checks in that case. let next_states: Vec<_> = states.iter().flat_map(|s| { // println!(" ... looking at {}{}", Self::format_state(s), *c as u8 as char); match c { @@ -65,31 +67,33 @@ impl ConditionRecord { let mut tmp = vec![]; let mut s1 = s.clone(); s1.push(Condition::Damaged); - if self.violates_constraints(&s1, true) { - // println!(" ... {:?} violates constraints", Self::format_state(&s1)); - } else { + if !self.violates_constraints(&s1, true) { // println!(" ... {:?} is acceptable", Self::format_state(&s1)); tmp.push(s1); + } else { + // println!(" ... {:?} violates constraints", Self::format_state(&s1)); } + let last = s.last(); let mut s2 = s.clone(); s2.push(Condition::Operational); - if self.violates_constraints(&s2, true) { - // println!(" ... {:?} violates constraints", Self::format_state(&s2)); - } else { + if (last.is_some_and(|lc| *lc == Condition::Operational) && *c == Condition::Operational) || !self.violates_constraints(&s2, true) { // println!(" ... {:?} is acceptable", Self::format_state(&s2)); tmp.push(s2); + } else { + // println!(" ... {:?} violates constraints", Self::format_state(&s2)); } tmp }, _ => { + let last = s.last(); let mut s1 = s.clone(); s1.push(*c); - if self.violates_constraints(&s1, true) { + if (last.is_some_and(|lc| *lc == Condition::Operational) && *c == Condition::Operational) || !self.violates_constraints(&s1, true) { + vec![s1] + } else { // println!(" ... {:?} violates constraints", Self::format_state(&s1)); vec![] - } else { - vec![s1] } } } From 7f48eae7e317bc09f31d6505e73a78f567d3433f Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 18 Dec 2023 11:56:53 +0100 Subject: [PATCH 095/120] Move to incremental checking of constraints --- src/day12.rs | 261 +++++++++++++++++++++++++++++---------------------- 1 file changed, 148 insertions(+), 113 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index d1d162f..19476ee 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -28,71 +28,150 @@ impl Display for Condition { } } -struct ConditionRecord { +// State when searching for arrangements +struct State { conditions: Vec, - damaged_spring_groups: Vec, + last_damaged_count: usize, + last_damaged_spring_groups_index: usize, + invalid: bool, + needs_constraint_check: bool, } -impl ConditionRecord { - #[cfg(test)] - pub fn new(conditions: &[Condition], damaged_spring_groups: &[usize]) -> ConditionRecord { - ConditionRecord { - conditions: conditions.to_vec(), - damaged_spring_groups: damaged_spring_groups.to_vec(), +impl State { + fn empty() -> State { + State { + conditions: vec![], + last_damaged_count: 0, + last_damaged_spring_groups_index: 0, + invalid: false, + needs_constraint_check: false, + } + } + fn and(&self, c: Condition) -> State { + if self.invalid { + panic!("cannot 'and' to an invalid state"); + } + let mut new_conditions = self.conditions.clone(); + new_conditions.push(c); + State { + conditions: new_conditions, + last_damaged_count: self.last_damaged_count, + last_damaged_spring_groups_index: self.last_damaged_spring_groups_index, + invalid: false, + needs_constraint_check: true, } } + + // Check whether the given conditions violates the constraints given by the `damaged_spring_groups` + // configuration. + // If `partial` is true then the check accepts conditions that are incomplete and could be completed + // to a full valid configuration, if it is false then the conditions must match perfectly. + fn check_constraints(&mut self, damaged_spring_groups: &[usize], partial: bool) -> bool { + // Invalid states stay invalid, and we can skip checks when nothing has changed + // since the last check. + if self.invalid || !self.needs_constraint_check { + return !self.invalid; + } + + // needs_constraint_check is true on a state that recently got a new condition, so we check + // whether the last condition is not breaking anything. + match self.conditions.last() { + Some(Condition::Operational) => { + // An operational condition was added, so any incomplete damaged group would now be complete and must match exactly + // the indicated group. + if self.last_damaged_count > 0 { + // A group was open, close it and match it. + if let Some(expected_damaged_count) = damaged_spring_groups.get(self.last_damaged_spring_groups_index) { + let result = *expected_damaged_count == self.last_damaged_count; + self.invalid = !result; + } else { + // State is invalid: keep the constraint check flag on for now, so that the next one + // will also flag it. + self.invalid = true; + } + self.last_damaged_count = 0; + self.last_damaged_spring_groups_index += 1; + } + }, + Some(Condition::Damaged) => { + // A damaged condition was added, so we need to check whether that is still fitting the current index. + self.last_damaged_count += 1; + if let Some(expected_damaged_count) = damaged_spring_groups.get(self.last_damaged_spring_groups_index) { + let result = if partial { + *expected_damaged_count >= self.last_damaged_count + } else { + *expected_damaged_count == self.last_damaged_count + }; + self.invalid = !result; + } else { + // State is invalid: keep the constraint check flag on for now, so that the next one + // will also flag it. + self.invalid = true; + } + }, + Some(condition) => { + panic!("unexpected condition {}", condition); + }, + None => { + // Nothing to do really, the thing is empty. But: How did you get here? + panic!("huh? state is empty"); + }, + } + + // If we're not doing a partial check, then the group index should point after the end + // of the groups, i.e. there is no missing group. + if !self.invalid && !partial { + self.invalid = self.last_damaged_spring_groups_index >= damaged_spring_groups.len(); + } + + // Mark check as done, and return whether we're now invalid or not. + self.needs_constraint_check = false; + !self.invalid + } +} + +impl Display for State { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let cond_str = std::str::from_utf8(&self.conditions.iter().map(|c| *c as u8).collect::>()).unwrap().to_string(); + write!(f, "\"{}\" (ldc = {}, i = {}", cond_str, self.last_damaged_count, self.last_damaged_spring_groups_index) + } +} + +struct ConditionRecord { + conditions: Vec, + damaged_spring_groups: Vec, +} + +impl ConditionRecord { pub fn num_arrangements(&self) -> usize { // Stupid logic: Each '?' can be either '.' or '#'. So, try both, and then proceed // and see if _at the end_. Essentially we're building a matching automaton here?????!?!?!! // Each state is the conditions we found. - let states: &mut Vec> = &mut vec![]; + let states: &mut Vec = &mut vec![]; // Start out with one empty state: - let initial_state = vec![]; - states.push(initial_state); + states.push(State::empty()); for c in &self.conditions { - // println!("{:?} with states {}", c, states.iter().map(|s| Self::format_state(s)).collect::>().join(",")); - - // Modify the states depending on the condition - // If we see a '.' or '#' then it will be added immediately to the states, which may - // make some switch from "could work" to "invalid". - // If we see a '?' we fork the state, and keep the the valid parts. - // Adding a '.' after a '.' will not actually change anything, so we can skip - // the checks in that case. let next_states: Vec<_> = states.iter().flat_map(|s| { - // println!(" ... looking at {}{}", Self::format_state(s), *c as u8 as char); match c { Condition::Unknown => { let mut tmp = vec![]; - let mut s1 = s.clone(); - s1.push(Condition::Damaged); - if !self.violates_constraints(&s1, true) { - // println!(" ... {:?} is acceptable", Self::format_state(&s1)); + let mut s1 = s.and(Condition::Damaged); + if s1.check_constraints(&self.damaged_spring_groups, true) { tmp.push(s1); - } else { - // println!(" ... {:?} violates constraints", Self::format_state(&s1)); } - - let last = s.last(); - let mut s2 = s.clone(); - s2.push(Condition::Operational); - if (last.is_some_and(|lc| *lc == Condition::Operational) && *c == Condition::Operational) || !self.violates_constraints(&s2, true) { - // println!(" ... {:?} is acceptable", Self::format_state(&s2)); + let mut s2 = s.and(Condition::Operational); + if s2.check_constraints(&self.damaged_spring_groups, true) { tmp.push(s2); - } else { - // println!(" ... {:?} violates constraints", Self::format_state(&s2)); } tmp }, - _ => { - let last = s.last(); - let mut s1 = s.clone(); - s1.push(*c); - if (last.is_some_and(|lc| *lc == Condition::Operational) && *c == Condition::Operational) || !self.violates_constraints(&s1, true) { + c => { + let mut s1 = s.and(*c); + if s1.check_constraints(&self.damaged_spring_groups, true) { vec![s1] } else { - // println!(" ... {:?} violates constraints", Self::format_state(&s1)); vec![] } } @@ -106,65 +185,13 @@ impl ConditionRecord { *states = next_states; } - states.iter().filter(|s| { - let ok = !self.violates_constraints(s, false); - // if ok { - // println!("{}", Self::format_state(s)); - // } - ok - }).count() - } - - // Check whether the given conditions violates the constraints given by the `damaged_spring_groups` - // configuration. - // If `partial` is true then the check accepts conditions that are incomplete and could be completed - // to a full valid configuration, if it is false then the conditions must match perfectly. - fn violates_constraints(&self, conditions: &[Condition], partial: bool) -> bool { - let mut next_spring_group = self.damaged_spring_groups.iter(); - let mut damaged_count = 0; - for c in conditions { - if *c == Condition::Operational { - if damaged_count > 0 { - match next_spring_group.next() { - Some(expected_damaged_count) => { - if *expected_damaged_count != damaged_count { - return true; - } - }, - None => { - return true; - }, - } - damaged_count = 0; - } - } else if *c == Condition::Damaged { - damaged_count += 1; - } else { - panic!("unexpected condition {:?}", c) - } - } - - // We're only checking whether the given conditions could still pass, so at this point - // we only want "close enough": If we collected some damaged springs, then the next value - // in the iteration must not be smaller than that. - // For a "full" check we would also verify that there is nothing left over at the end, and - // any collected damamged springs would have to match exactly. - match next_spring_group.next() { - Some(expected_damaged_count) => { - if partial { - damaged_count > *expected_damaged_count - } else { - damaged_count != *expected_damaged_count || next_spring_group.next().is_some() - } - } - None => { - damaged_count > 0 + let mut result = 0; + for s in states.iter_mut() { + if s.check_constraints(&self.damaged_spring_groups, false) { + result += 1; } } - } - - fn format_state(state: &[Condition]) -> String { - std::str::from_utf8(&state.iter().map(|c| *c as u8).collect::>()).unwrap().to_string() + result } fn parse_state(s: &str) -> Vec { @@ -253,26 +280,34 @@ mod tests { } } + fn build_state(s: &str, damaged_spring_groups: &[usize]) -> Result { + let mut result = State::empty(); + for c in s.chars() { + let cond = Condition::from(c); + result = result.and(cond); + if !result.check_constraints(damaged_spring_groups, true) { + return Err("cannot build state"); + } + } + Ok(result) + } + #[test] - fn condition_record_violates_constraints_partial() { - assert!(!ConditionRecord::new(&[], &[]).violates_constraints(&[], true), "empty allows empty"); - assert!(!ConditionRecord::new(&[], &[1]).violates_constraints(&[], true), "non-empty allows empty"); - assert!(!ConditionRecord::new(&[], &[1]).violates_constraints(&[Condition::Damaged], true), "must match single"); - assert!(!ConditionRecord::new(&[], &[2,1]).violates_constraints(&[Condition::Damaged, Condition::Damaged, Condition::Operational, Condition::Damaged], true), "must match multiple with operational in the middle"); - assert!(!ConditionRecord::new(&[], &[2,2]).violates_constraints(&[Condition::Damaged, Condition::Damaged, Condition::Operational, Condition::Damaged], true), "last can be incomplete"); + fn state_check_constraints_partial() { + assert!(State::empty().check_constraints(&[], true), "empty allows empty"); + let dsg1 = &[1]; + assert!(State::empty().check_constraints(dsg1, true), "non-empty allows empty"); + assert!(build_state("#", dsg1).unwrap().check_constraints(dsg1, true), "must match single"); + let dsg21 = &[2, 1]; + assert!(build_state("##.#", dsg21).unwrap().check_constraints(dsg21, true), "must match multiple with operational in the middle"); + let dsg22 = &[2, 2]; + assert!(build_state("##.#", dsg22).unwrap().check_constraints(dsg22, true), "last can be incomplete"); } #[test] - fn condition_record_violates_constraints_partial_small() { - assert!(ConditionRecord::new(&[], &[3,2,1]).violates_constraints(&[ - Condition::Operational, - Condition::Damaged, - Condition::Damaged, - Condition::Damaged, - Condition::Operational, - Condition::Damaged, - Condition::Operational, - ], false)); + fn state_check_constraints_small() { + let dsg321 = &[3, 2, 1]; + assert!(build_state(".###.#.", dsg321).is_err()); } #[test] From 0b8d66a107b807699191f99491fb7a093eded722 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 18 Dec 2023 13:38:41 +0100 Subject: [PATCH 096/120] Make tests pass for part 2 --- src/day12.rs | 248 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 171 insertions(+), 77 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index 19476ee..12aab52 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -1,4 +1,4 @@ -use std::{str::FromStr, fmt::Display}; +use std::fmt::Display; #[derive(Clone, Copy, Debug, PartialEq)] enum Condition { @@ -31,34 +31,32 @@ impl Display for Condition { // State when searching for arrangements struct State { conditions: Vec, + unchecked_conditions: Vec, last_damaged_count: usize, last_damaged_spring_groups_index: usize, invalid: bool, - needs_constraint_check: bool, } impl State { fn empty() -> State { State { conditions: vec![], + unchecked_conditions: vec![], last_damaged_count: 0, last_damaged_spring_groups_index: 0, invalid: false, - needs_constraint_check: false, } } fn and(&self, c: Condition) -> State { if self.invalid { panic!("cannot 'and' to an invalid state"); } - let mut new_conditions = self.conditions.clone(); - new_conditions.push(c); State { - conditions: new_conditions, + conditions: self.conditions.clone(), + unchecked_conditions: vec![c], last_damaged_count: self.last_damaged_count, last_damaged_spring_groups_index: self.last_damaged_spring_groups_index, invalid: false, - needs_constraint_check: true, } } @@ -68,65 +66,90 @@ impl State { // If `partial` is true then the check accepts conditions that are incomplete and could be completed // to a full valid configuration, if it is false then the conditions must match perfectly. fn check_constraints(&mut self, damaged_spring_groups: &[usize], partial: bool) -> bool { - // Invalid states stay invalid, and we can skip checks when nothing has changed + // Invalid states stay invalid, and we can skip partial checks when nothing has changed // since the last check. - if self.invalid || !self.needs_constraint_check { + if self.invalid || (partial && self.unchecked_conditions.is_empty()) { + // if cfg!(test) { + // println!("check_constraints({}): early exit", self); + // } return !self.invalid; } - // needs_constraint_check is true on a state that recently got a new condition, so we check - // whether the last condition is not breaking anything. - match self.conditions.last() { - Some(Condition::Operational) => { - // An operational condition was added, so any incomplete damaged group would now be complete and must match exactly - // the indicated group. - if self.last_damaged_count > 0 { - // A group was open, close it and match it. + // Process all unchecked conditions + for c in self.unchecked_conditions.iter() { + // if cfg!(test) { + // print!("check_constraints(): applying {}", c); + // } + match c { + Condition::Operational => { + // An operational condition was added, so any incomplete damaged group would now be complete and must match exactly + // the indicated group. + if self.last_damaged_count > 0 { + // A group was open, close it and match it. + if let Some(expected_damaged_count) = damaged_spring_groups.get(self.last_damaged_spring_groups_index) { + let result = *expected_damaged_count == self.last_damaged_count; + self.invalid = !result; + } else { + // State is invalid: keep the constraint check flag on for now, so that the next one + // will also flag it. + self.invalid = true; + } + self.last_damaged_count = 0; + self.last_damaged_spring_groups_index += 1; + } + }, + Condition::Damaged => { + // A damaged condition was added, so we need to check whether that is still fitting the current index. + self.last_damaged_count += 1; if let Some(expected_damaged_count) = damaged_spring_groups.get(self.last_damaged_spring_groups_index) { - let result = *expected_damaged_count == self.last_damaged_count; + let result = if partial { + *expected_damaged_count >= self.last_damaged_count + } else { + *expected_damaged_count == self.last_damaged_count + }; self.invalid = !result; } else { // State is invalid: keep the constraint check flag on for now, so that the next one // will also flag it. self.invalid = true; } - self.last_damaged_count = 0; - self.last_damaged_spring_groups_index += 1; - } - }, - Some(Condition::Damaged) => { - // A damaged condition was added, so we need to check whether that is still fitting the current index. - self.last_damaged_count += 1; - if let Some(expected_damaged_count) = damaged_spring_groups.get(self.last_damaged_spring_groups_index) { - let result = if partial { - *expected_damaged_count >= self.last_damaged_count - } else { - *expected_damaged_count == self.last_damaged_count - }; - self.invalid = !result; - } else { - // State is invalid: keep the constraint check flag on for now, so that the next one - // will also flag it. - self.invalid = true; - } - }, - Some(condition) => { - panic!("unexpected condition {}", condition); - }, - None => { - // Nothing to do really, the thing is empty. But: How did you get here? - panic!("huh? state is empty"); - }, + }, + condition => { + panic!("unexpected condition {}", condition); + }, + }; + self.conditions.push(*c); + if self.invalid { + // if cfg!(test) { + // println!(": invalid, breaking"); + // } + break; + } else { + // if cfg!(test) { + // println!() + // } + } } + // Mark check as done, and return whether we're now invalid or not. + self.unchecked_conditions.clear(); - // If we're not doing a partial check, then the group index should point after the end - // of the groups, i.e. there is no missing group. + // If we're not doing a partial check, then the group index should point to the last group + // if the last condition was damaged, or to after the end so that there are no missing groups. + // println!("... invalid after applying unchecked = {}", self.invalid); if !self.invalid && !partial { - self.invalid = self.last_damaged_spring_groups_index >= damaged_spring_groups.len(); + // print!("... not partial, checking group index {}", self.last_damaged_spring_groups_index); + match self.conditions.last() { + Some(Condition::Damaged) => { + // Invalid if not exactly pointing to the last. + self.invalid = self.last_damaged_spring_groups_index != damaged_spring_groups.len() - 1; + }, + _ => { + // Empty or last one was operational, invalid if not after the end + self.invalid = self.last_damaged_spring_groups_index != damaged_spring_groups.len(); + }, + }; } - // Mark check as done, and return whether we're now invalid or not. - self.needs_constraint_check = false; !self.invalid } } @@ -134,7 +157,8 @@ impl State { impl Display for State { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let cond_str = std::str::from_utf8(&self.conditions.iter().map(|c| *c as u8).collect::>()).unwrap().to_string(); - write!(f, "\"{}\" (ldc = {}, i = {}", cond_str, self.last_damaged_count, self.last_damaged_spring_groups_index) + let unchecked_cond_str = std::str::from_utf8(&self.unchecked_conditions.iter().map(|c| *c as u8).collect::>()).unwrap().to_string(); + write!(f, "\"{}\" (ldc = {}, i = {}, invalid = {}, unchecked = {:?})", cond_str, self.last_damaged_count, self.last_damaged_spring_groups_index, self.invalid, unchecked_cond_str) } } @@ -144,6 +168,22 @@ struct ConditionRecord { } impl ConditionRecord { + pub fn repeat(&self, n: usize) -> ConditionRecord { + let mut new_conditions = vec![]; + for i in 0..n { + for c in &self.conditions { + new_conditions.push(*c); + } + if i != n-1 { + new_conditions.push(Condition::Unknown); + } + } + ConditionRecord { + conditions: new_conditions, + damaged_spring_groups: self.damaged_spring_groups.repeat(n,) + } + } + pub fn num_arrangements(&self) -> usize { // Stupid logic: Each '?' can be either '.' or '#'. So, try both, and then proceed // and see if _at the end_. Essentially we're building a matching automaton here?????!?!?!! @@ -154,28 +194,50 @@ impl ConditionRecord { states.push(State::empty()); for c in &self.conditions { let next_states: Vec<_> = states.iter().flat_map(|s| { - match c { + // if cfg!(test) { + // print!("state = {}, c = {}", s, c); + // } + let new_states = match c { Condition::Unknown => { + // if cfg!(test) { + // print!(": unknown"); + // } let mut tmp = vec![]; let mut s1 = s.and(Condition::Damaged); if s1.check_constraints(&self.damaged_spring_groups, true) { + // if cfg!(test) { + // print!(", s1 = {} is valid", s1); + // } tmp.push(s1); } let mut s2 = s.and(Condition::Operational); if s2.check_constraints(&self.damaged_spring_groups, true) { + // if cfg!(test) { + // print!(", s2 = {} is valid", s2); + // } tmp.push(s2); } tmp }, c => { + // if cfg!(test) { + // print!(": definite"); + // } let mut s1 = s.and(*c); if s1.check_constraints(&self.damaged_spring_groups, true) { + // if cfg!(test) { + // print!(", s1 = {} is valid", s1); + // } vec![s1] } else { vec![] } } - } + }; + // if cfg!(test) { + // println!(); + // } + new_states }).collect(); // println!(" ... next_states = {}", next_states.iter().map(|s| self.format_state(s)).collect::>().join(",")); if next_states.is_empty() { @@ -187,8 +249,14 @@ impl ConditionRecord { let mut result = 0; for s in states.iter_mut() { - if s.check_constraints(&self.damaged_spring_groups, false) { + let valid = s.check_constraints(&self.damaged_spring_groups, false); + if valid { + // println!("state = {}: counted, valid at full", s); result += 1; + } else { + // if cfg!(test) { + // println!("state = {}: pruned, invalid at full", s); + // } } } result @@ -219,30 +287,15 @@ impl std::str::FromStr for ConditionRecord { } } -fn num_arrangements(input: &str) -> usize { - input.split('\n').map(ConditionRecord::from_str).map(|cr| cr.unwrap().num_arrangements()).sum() -} - -// See https://stackoverflow.com/a/66482767/196315 -fn repeat_element(it: impl Iterator, cnt: usize) -> impl Iterator { - it.flat_map(move |n| std::iter::repeat(n).take(cnt)) +fn num_arrangements(input: &str, repeat: usize) -> usize { + input.split('\n').map(str::parse::).map(|cr| cr.unwrap().repeat(repeat).num_arrangements()).sum() } pub fn main() { match std::fs::read_to_string("day12.input") { Ok(input) => { - println!("num_arrangements = {}", num_arrangements(&input)); - let num_arrangements_part2: usize = input.split('\n').filter_map(|i| { - if let Some((p, g)) = i.split_once(' ') { - format!("{} {}", - repeat_element(std::iter::once(p), 5).collect::>().join("?"), - repeat_element(std::iter::once(g), 5).collect::>().join(","), - ).parse::().ok() - } else { - None - } - }).map(|cr| cr.num_arrangements()).sum(); - println!("num_arrangements (part 2) = {}", num_arrangements_part2); + println!("num_arrangements = {}", num_arrangements(&input, 1)); + println!("num_arrangements (part 2) = {}", num_arrangements(&input, 5)); }, Err(reason) => println!("error = {}", reason) } @@ -311,23 +364,64 @@ mod tests { } #[test] - fn example1_small() { - assert_eq!("?###???????? 3,2,1".parse::().unwrap().num_arrangements(), 10); + fn example1_small_1() { + let dsg = &[3, 2, 1]; + let mut s = build_state(".###.##....#", dsg).unwrap(); + assert_eq!(s.last_damaged_count, 1); + assert_eq!(s.last_damaged_spring_groups_index, 2); + let valid_at_full = s.check_constraints(dsg, false); + assert!(valid_at_full); + } + + #[test] + fn example1_small_2() { + let dsg = &[1, 1, 3]; + let mut s = build_state(".#...#....###.", dsg).unwrap(); + assert_eq!(s.last_damaged_count, 0); + assert_eq!(s.last_damaged_spring_groups_index, 3); + let valid_at_full = s.check_constraints(dsg, false); + assert!(valid_at_full); } #[test] - fn example1() { + fn example1_part1() { assert_eq!("???.### 1,1,3".parse::().unwrap().num_arrangements(), 1); assert_eq!(".??..??...?##. 1,1,3".parse::().unwrap().num_arrangements(), 4); assert_eq!("?#?#?#?#?#?#?#? 1,3,1,6".parse::().unwrap().num_arrangements(), 1); assert_eq!("????.#...#... 4,1,1".parse::().unwrap().num_arrangements(), 1); assert_eq!("????.######..#####. 1,6,5".parse::().unwrap().num_arrangements(), 4); + assert_eq!("?###???????? 3,2,1".parse::().unwrap().num_arrangements(), 10); - assert_eq!(num_arrangements(DATA), 21) + assert_eq!(num_arrangements(DATA, 1), 21) } #[test] fn part1_tests() { assert_eq!("???.#??#.??? 1,1,2,1".parse::().unwrap().num_arrangements(), 10); } + + #[test] + fn condition_record_repeat() { + let cr = ".# 1".parse::().unwrap().repeat(2); + assert_eq!(cr.conditions, vec![ + Condition::Operational, + Condition::Damaged, + Condition::Unknown, + Condition::Operational, + Condition::Damaged, + ]); + assert_eq!(cr.damaged_spring_groups, vec![1,1]); + } + + #[test] + fn example1_part2() { + assert_eq!("???.### 1,1,3".parse::().unwrap().repeat(5).num_arrangements(), 1); + assert_eq!(".??..??...?##. 1,1,3".parse::().unwrap().repeat(5).num_arrangements(), 16384); + assert_eq!("?#?#?#?#?#?#?#? 1,3,1,6".parse::().unwrap().repeat(5).num_arrangements(), 1); + assert_eq!("????.#...#... 4,1,1".parse::().unwrap().repeat(5).num_arrangements(), 16); + assert_eq!("????.######..#####. 1,6,5".parse::().unwrap().repeat(5).num_arrangements(), 2500); + assert_eq!("?###???????? 3,2,1".parse::().unwrap().repeat(5).num_arrangements(), 506250); + + assert_eq!(num_arrangements(DATA, 5), 525152) + } } \ No newline at end of file From 2d0bd505f3f2d19f89dac8d7796c0cd379e55e22 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 14:27:17 +0100 Subject: [PATCH 097/120] Fix implementation to count correctly compared to the original version This adds regression tests: We know the initial implementation for part 1 is correct (up to the tests that AoC does there), so the new implementation needs to minimally produce the same results there. --- src/day12.rs | 231 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 186 insertions(+), 45 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index 12aab52..2591e7c 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -65,21 +65,21 @@ impl State { // configuration. // If `partial` is true then the check accepts conditions that are incomplete and could be completed // to a full valid configuration, if it is false then the conditions must match perfectly. - fn check_constraints(&mut self, damaged_spring_groups: &[usize], partial: bool) -> bool { + fn check_constraints(&mut self, damaged_spring_groups: &[usize], partial: bool, print: bool) -> bool { // Invalid states stay invalid, and we can skip partial checks when nothing has changed // since the last check. if self.invalid || (partial && self.unchecked_conditions.is_empty()) { - // if cfg!(test) { - // println!("check_constraints({}): early exit", self); - // } + if print { + println!("check_constraints({}): early exit", self); + } return !self.invalid; } // Process all unchecked conditions for c in self.unchecked_conditions.iter() { - // if cfg!(test) { - // print!("check_constraints(): applying {}", c); - // } + if print { + print!("check_constraints(): applying {}", c); + } match c { Condition::Operational => { // An operational condition was added, so any incomplete damaged group would now be complete and must match exactly @@ -102,12 +102,7 @@ impl State { // A damaged condition was added, so we need to check whether that is still fitting the current index. self.last_damaged_count += 1; if let Some(expected_damaged_count) = damaged_spring_groups.get(self.last_damaged_spring_groups_index) { - let result = if partial { - *expected_damaged_count >= self.last_damaged_count - } else { - *expected_damaged_count == self.last_damaged_count - }; - self.invalid = !result; + self.invalid = *expected_damaged_count < self.last_damaged_count; } else { // State is invalid: keep the constraint check flag on for now, so that the next one // will also flag it. @@ -120,14 +115,14 @@ impl State { }; self.conditions.push(*c); if self.invalid { - // if cfg!(test) { - // println!(": invalid, breaking"); - // } + if print { + println!(": invalid, breaking"); + } break; } else { - // if cfg!(test) { - // println!() - // } + if print { + println!() + } } } // Mark check as done, and return whether we're now invalid or not. @@ -137,11 +132,18 @@ impl State { // if the last condition was damaged, or to after the end so that there are no missing groups. // println!("... invalid after applying unchecked = {}", self.invalid); if !self.invalid && !partial { - // print!("... not partial, checking group index {}", self.last_damaged_spring_groups_index); + if print { + print!("... not partial, checking group index {}", self.last_damaged_spring_groups_index); + } match self.conditions.last() { Some(Condition::Damaged) => { - // Invalid if not exactly pointing to the last. - self.invalid = self.last_damaged_spring_groups_index != damaged_spring_groups.len() - 1; + // Invalid + // - if last damage count was not exactly the last group, or + // - if not exactly pointing to the last. + if let Some(expected_damaged_count) = damaged_spring_groups.get(self.last_damaged_spring_groups_index) { + self.invalid = *expected_damaged_count != self.last_damaged_count; + } + self.invalid |= self.last_damaged_spring_groups_index != damaged_spring_groups.len() - 1; }, _ => { // Empty or last one was operational, invalid if not after the end @@ -180,11 +182,15 @@ impl ConditionRecord { } ConditionRecord { conditions: new_conditions, - damaged_spring_groups: self.damaged_spring_groups.repeat(n,) + damaged_spring_groups: self.damaged_spring_groups.repeat(n), } } pub fn num_arrangements(&self) -> usize { + self.arrangements().len() + } + + fn arrangements(&self) -> Vec { // Stupid logic: Each '?' can be either '.' or '#'. So, try both, and then proceed // and see if _at the end_. Essentially we're building a matching automaton here?????!?!?!! // Each state is the conditions we found. @@ -204,14 +210,14 @@ impl ConditionRecord { // } let mut tmp = vec![]; let mut s1 = s.and(Condition::Damaged); - if s1.check_constraints(&self.damaged_spring_groups, true) { + if s1.check_constraints(&self.damaged_spring_groups, true, false) { // if cfg!(test) { // print!(", s1 = {} is valid", s1); // } tmp.push(s1); } let mut s2 = s.and(Condition::Operational); - if s2.check_constraints(&self.damaged_spring_groups, true) { + if s2.check_constraints(&self.damaged_spring_groups, true, false) { // if cfg!(test) { // print!(", s2 = {} is valid", s2); // } @@ -224,7 +230,7 @@ impl ConditionRecord { // print!(": definite"); // } let mut s1 = s.and(*c); - if s1.check_constraints(&self.damaged_spring_groups, true) { + if s1.check_constraints(&self.damaged_spring_groups, true, false) { // if cfg!(test) { // print!(", s1 = {} is valid", s1); // } @@ -241,22 +247,22 @@ impl ConditionRecord { }).collect(); // println!(" ... next_states = {}", next_states.iter().map(|s| self.format_state(s)).collect::>().join(",")); if next_states.is_empty() { - println!("no more states, can return 0 early"); - return 0; + println!("no more states, can return empty early"); + return vec![]; } *states = next_states; } - let mut result = 0; + // Filter out the invalid states + let mut result = vec![]; for s in states.iter_mut() { - let valid = s.check_constraints(&self.damaged_spring_groups, false); + let valid = s.check_constraints(&self.damaged_spring_groups, false, false); if valid { // println!("state = {}: counted, valid at full", s); - result += 1; + let cond_str = std::str::from_utf8(&s.conditions.iter().map(|c| *c as u8).collect::>()).unwrap().to_string(); + result.push(cond_str); } else { - // if cfg!(test) { - // println!("state = {}: pruned, invalid at full", s); - // } + // println!("state = {}: pruned, invalid at full", s); } } result @@ -265,6 +271,121 @@ impl ConditionRecord { fn parse_state(s: &str) -> Vec { s.chars().map(Condition::from).collect() } + + // OLD + #[cfg(test)] + pub fn num_arrangements_old(&self) -> usize { + // Stupid logic: Each '?' can be either '.' or '#'. So, try both, and then proceed + // and see if _at the end_. Essentially we're building a matching automaton here?????!?!?!! + // Each state is the conditions we found. + let states: &mut Vec> = &mut vec![]; + + // Start out with one empty state: + let initial_state = vec![]; + states.push(initial_state); + for c in &self.conditions { + // println!("{:?} with states {}", c, states.iter().map(|s| Self::format_state(s)).collect::>().join(",")); + + // Modify the states depending on the condition + // If we see a '.' or '#' then it will be added immediately to the states, which may + // make some switch from "could work" to "invalid". + // If we see a '?' we fork the state, and keep the the valid parts. + let next_states: Vec<_> = states.iter().flat_map(|s| { + // println!(" ... looking at {}{}", Self::format_state(s), *c as u8 as char); + match c { + Condition::Unknown => { + let mut tmp = vec![]; + let mut s1 = s.clone(); + s1.push(Condition::Damaged); + if self.violates_constraints(&s1, true) { + // println!(" ... {:?} violates constraints", Self::format_state(&s1)); + } else { + // println!(" ... {:?} is acceptable", Self::format_state(&s1)); + tmp.push(s1); + } + + let mut s2 = s.clone(); + s2.push(Condition::Operational); + if self.violates_constraints(&s2, true) { + // println!(" ... {:?} violates constraints", Self::format_state(&s2)); + } else { + // println!(" ... {:?} is acceptable", Self::format_state(&s2)); + tmp.push(s2); + } + tmp + }, + _ => { + let mut s1 = s.clone(); + s1.push(*c); + if self.violates_constraints(&s1, true) { + // println!(" ... {:?} violates constraints", Self::format_state(&s1)); + vec![] + } else { + vec![s1] + } + } + } + }).collect(); + // println!(" ... next_states = {}", next_states.iter().map(|s| self.format_state(s)).collect::>().join(",")); + if next_states.is_empty() { + println!("no more states, can return 0 early"); + return 0; + } + *states = next_states; + } + + states.iter().filter(|s| !self.violates_constraints(s, false)).count() + } + + // Check whether the given conditions violates the constraints given by the `damaged_spring_groups` + // configuration. + // If `partial` is true then the check accepts conditions that are incomplete and could be completed + // to a full valid configuration, if it is false then the conditions must match perfectly. + #[cfg(test)] + fn violates_constraints(&self, conditions: &[Condition], partial: bool) -> bool { + let mut next_spring_group = self.damaged_spring_groups.iter(); + let mut damaged_count = 0; + for c in conditions { + if *c == Condition::Operational { + if damaged_count > 0 { + match next_spring_group.next() { + Some(expected_damaged_count) => { + if *expected_damaged_count != damaged_count { + return true; + } + }, + None => { + return true; + }, + } + damaged_count = 0; + } + } else if *c == Condition::Damaged { + damaged_count += 1; + } else { + panic!("unexpected condition {:?}", c) + } + } + + // We're only checking whether the given conditions could still pass, so at this point + // we only want "close enough": If we collected some damaged springs, then the next value + // in the iteration must not be smaller than that. + // For a "full" check we would also verify that there is nothing left over at the end, and + // any collected damamged springs would have to match exactly. + match next_spring_group.next() { + Some(expected_damaged_count) => { + if partial { + damaged_count > *expected_damaged_count + } else { + damaged_count != *expected_damaged_count || next_spring_group.next().is_some() + } + } + None => { + damaged_count > 0 + } + } + } + // END: OLD } impl std::str::FromStr for ConditionRecord { @@ -338,7 +459,7 @@ mod tests { for c in s.chars() { let cond = Condition::from(c); result = result.and(cond); - if !result.check_constraints(damaged_spring_groups, true) { + if !result.check_constraints(damaged_spring_groups, true, false) { return Err("cannot build state"); } } @@ -347,14 +468,14 @@ mod tests { #[test] fn state_check_constraints_partial() { - assert!(State::empty().check_constraints(&[], true), "empty allows empty"); + assert!(State::empty().check_constraints(&[], true, false), "empty allows empty"); let dsg1 = &[1]; - assert!(State::empty().check_constraints(dsg1, true), "non-empty allows empty"); - assert!(build_state("#", dsg1).unwrap().check_constraints(dsg1, true), "must match single"); + assert!(State::empty().check_constraints(dsg1, true, false), "non-empty allows empty"); + assert!(build_state("#", dsg1).unwrap().check_constraints(dsg1, true, false), "must match single"); let dsg21 = &[2, 1]; - assert!(build_state("##.#", dsg21).unwrap().check_constraints(dsg21, true), "must match multiple with operational in the middle"); + assert!(build_state("##.#", dsg21).unwrap().check_constraints(dsg21, true, false), "must match multiple with operational in the middle"); let dsg22 = &[2, 2]; - assert!(build_state("##.#", dsg22).unwrap().check_constraints(dsg22, true), "last can be incomplete"); + assert!(build_state("##.#", dsg22).unwrap().check_constraints(dsg22, true, false), "last can be incomplete"); } #[test] @@ -369,7 +490,7 @@ mod tests { let mut s = build_state(".###.##....#", dsg).unwrap(); assert_eq!(s.last_damaged_count, 1); assert_eq!(s.last_damaged_spring_groups_index, 2); - let valid_at_full = s.check_constraints(dsg, false); + let valid_at_full = s.check_constraints(dsg, false, false); assert!(valid_at_full); } @@ -379,10 +500,10 @@ mod tests { let mut s = build_state(".#...#....###.", dsg).unwrap(); assert_eq!(s.last_damaged_count, 0); assert_eq!(s.last_damaged_spring_groups_index, 3); - let valid_at_full = s.check_constraints(dsg, false); + let valid_at_full = s.check_constraints(dsg, false, false); assert!(valid_at_full); } - + #[test] fn example1_part1() { assert_eq!("???.### 1,1,3".parse::().unwrap().num_arrangements(), 1); @@ -397,7 +518,12 @@ mod tests { #[test] fn part1_tests() { - assert_eq!("???.#??#.??? 1,1,2,1".parse::().unwrap().num_arrangements(), 10); + //assert_eq!("???.#??#.??? 1,1,2,1".parse::().unwrap().num_arrangements(), 10); + let cr = "##???#??#?????????#? 11,6".parse::().unwrap(); + assert_eq!(cr.arrangements(), &[ + "###########..######.", + "###########...######", + ]); } #[test] @@ -424,4 +550,19 @@ mod tests { assert_eq!(num_arrangements(DATA, 5), 525152) } -} \ No newline at end of file + + #[test] + fn old_vs_new() { + match std::fs::read_to_string("day12.input") { + Ok(input) => { + for line in input.split('\n') { + let cr = line.parse::().unwrap(); + let old = cr.num_arrangements_old(); + let new = cr.num_arrangements(); + assert_eq!(new, old, "old = {}, new = {}", old, new); + } + }, + Err(reason) => println!("error = {}", reason) + } + } +} From ce70d3f58393e568188e79f818850acf22caa171 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 14:38:06 +0100 Subject: [PATCH 098/120] Factor out the logic for handling yet-unchecked conditions --- src/day12.rs | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index 2591e7c..8fbf267 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -60,22 +60,11 @@ impl State { } } - - // Check whether the given conditions violates the constraints given by the `damaged_spring_groups` - // configuration. - // If `partial` is true then the check accepts conditions that are incomplete and could be completed - // to a full valid configuration, if it is false then the conditions must match perfectly. - fn check_constraints(&mut self, damaged_spring_groups: &[usize], partial: bool, print: bool) -> bool { - // Invalid states stay invalid, and we can skip partial checks when nothing has changed - // since the last check. - if self.invalid || (partial && self.unchecked_conditions.is_empty()) { - if print { - println!("check_constraints({}): early exit", self); - } - return !self.invalid; + fn apply_unchecked_conditions(&mut self, damaged_spring_groups: &[usize], print: bool) { + if self.unchecked_conditions.is_empty() { + return } - // Process all unchecked conditions for c in self.unchecked_conditions.iter() { if print { print!("check_constraints(): applying {}", c); @@ -127,6 +116,24 @@ impl State { } // Mark check as done, and return whether we're now invalid or not. self.unchecked_conditions.clear(); + } + + // Check whether the given conditions violates the constraints given by the `damaged_spring_groups` + // configuration. + // If `partial` is true then the check accepts conditions that are incomplete and could be completed + // to a full valid configuration, if it is false then the conditions must match perfectly. + fn check_constraints(&mut self, damaged_spring_groups: &[usize], partial: bool, print: bool) -> bool { + // Invalid states stay invalid, and we can skip partial checks when nothing has changed + // since the last check. + if self.invalid || (partial && self.unchecked_conditions.is_empty()) { + if print { + println!("check_constraints({}): early exit", self); + } + return !self.invalid; + } + + // Process all unchecked conditions + self.apply_unchecked_conditions(damaged_spring_groups, print); // If we're not doing a partial check, then the group index should point to the last group // if the last condition was damaged, or to after the end so that there are no missing groups. From 5c93556f14c9c9dccf74198dc488b0462e326381 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 15:25:25 +0100 Subject: [PATCH 099/120] There can be at most one unchecked condition --- src/day12.rs | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index 8fbf267..f50159d 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -31,7 +31,7 @@ impl Display for Condition { // State when searching for arrangements struct State { conditions: Vec, - unchecked_conditions: Vec, + unchecked_condition: Option, last_damaged_count: usize, last_damaged_spring_groups_index: usize, invalid: bool, @@ -41,7 +41,7 @@ impl State { fn empty() -> State { State { conditions: vec![], - unchecked_conditions: vec![], + unchecked_condition: None, last_damaged_count: 0, last_damaged_spring_groups_index: 0, invalid: false, @@ -51,9 +51,12 @@ impl State { if self.invalid { panic!("cannot 'and' to an invalid state"); } + if self.unchecked_condition.is_some() { + panic!("cannot 'and' to a state with unchecked conditions"); + } State { conditions: self.conditions.clone(), - unchecked_conditions: vec![c], + unchecked_condition: Some(c), last_damaged_count: self.last_damaged_count, last_damaged_spring_groups_index: self.last_damaged_spring_groups_index, invalid: false, @@ -61,11 +64,7 @@ impl State { } fn apply_unchecked_conditions(&mut self, damaged_spring_groups: &[usize], print: bool) { - if self.unchecked_conditions.is_empty() { - return - } - - for c in self.unchecked_conditions.iter() { + if let Some(c) = self.unchecked_condition { if print { print!("check_constraints(): applying {}", c); } @@ -102,20 +101,14 @@ impl State { panic!("unexpected condition {}", condition); }, }; - self.conditions.push(*c); - if self.invalid { - if print { - println!(": invalid, breaking"); - } - break; - } else { - if print { - println!() - } + + // Consume the unchecked condition + self.unchecked_condition = None; + self.conditions.push(c); + if print { + println!(": invalid = {}", self.invalid); } } - // Mark check as done, and return whether we're now invalid or not. - self.unchecked_conditions.clear(); } // Check whether the given conditions violates the constraints given by the `damaged_spring_groups` @@ -125,7 +118,7 @@ impl State { fn check_constraints(&mut self, damaged_spring_groups: &[usize], partial: bool, print: bool) -> bool { // Invalid states stay invalid, and we can skip partial checks when nothing has changed // since the last check. - if self.invalid || (partial && self.unchecked_conditions.is_empty()) { + if self.invalid || (partial && self.unchecked_condition.is_none()) { if print { println!("check_constraints({}): early exit", self); } @@ -166,8 +159,15 @@ impl State { impl Display for State { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let cond_str = std::str::from_utf8(&self.conditions.iter().map(|c| *c as u8).collect::>()).unwrap().to_string(); - let unchecked_cond_str = std::str::from_utf8(&self.unchecked_conditions.iter().map(|c| *c as u8).collect::>()).unwrap().to_string(); - write!(f, "\"{}\" (ldc = {}, i = {}, invalid = {}, unchecked = {:?})", cond_str, self.last_damaged_count, self.last_damaged_spring_groups_index, self.invalid, unchecked_cond_str) + let r = write!(f, "\"{}\" (ldc = {}, i = {}, invalid = {}", cond_str, self.last_damaged_count, self.last_damaged_spring_groups_index, self.invalid); + if r.is_err() { + panic!("cannot format state"); + } + if let Some(unchecked_condition) = self.unchecked_condition { + write!(f, ", unchecked = {})", unchecked_condition) + } else { + write!(f, ")") + } } } @@ -378,7 +378,7 @@ impl ConditionRecord { // we only want "close enough": If we collected some damaged springs, then the next value // in the iteration must not be smaller than that. // For a "full" check we would also verify that there is nothing left over at the end, and - // any collected damamged springs would have to match exactly. + // any collected damaged springs would have to match exactly. match next_spring_group.next() { Some(expected_damaged_count) => { if partial { From 0cd650a094eadab2d936bdc477adf776affb506b Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 16:03:59 +0100 Subject: [PATCH 100/120] Use `drain()` to stop leaking more memory than needed This still explodes, but at least now we could just let it run for a while and see. --- src/day12.rs | 113 ++++++++++++++++++++------------------------------- 1 file changed, 45 insertions(+), 68 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index f50159d..b7efb43 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -29,6 +29,7 @@ impl Display for Condition { } // State when searching for arrangements +#[derive(Clone, Debug)] struct State { conditions: Vec, unchecked_condition: Option, @@ -194,10 +195,33 @@ impl ConditionRecord { } pub fn num_arrangements(&self) -> usize { - self.arrangements().len() + self.arrangements(false).len() } - fn arrangements(&self) -> Vec { + fn process_state(&self, s: State, c: Condition) -> Vec { + let mut result = vec![]; + match c { + Condition::Unknown => { + let mut s1 = s.and(Condition::Damaged); + if s1.check_constraints(&self.damaged_spring_groups, true, false) { + result.push(s1); + } + let mut s2 = s.and(Condition::Operational); + if s2.check_constraints(&self.damaged_spring_groups, true, false) { + result.push(s2); + } + }, + c => { + let mut s1 = s.and(c); + if s1.check_constraints(&self.damaged_spring_groups, true, false) { + result.push(s1); + } + } + } + result + } + + fn arrangements(&self, print: bool) -> Vec { // Stupid logic: Each '?' can be either '.' or '#'. So, try both, and then proceed // and see if _at the end_. Essentially we're building a matching automaton here?????!?!?!! // Each state is the conditions we found. @@ -205,59 +229,19 @@ impl ConditionRecord { // Start out with one empty state: states.push(State::empty()); - for c in &self.conditions { - let next_states: Vec<_> = states.iter().flat_map(|s| { - // if cfg!(test) { - // print!("state = {}, c = {}", s, c); - // } - let new_states = match c { - Condition::Unknown => { - // if cfg!(test) { - // print!(": unknown"); - // } - let mut tmp = vec![]; - let mut s1 = s.and(Condition::Damaged); - if s1.check_constraints(&self.damaged_spring_groups, true, false) { - // if cfg!(test) { - // print!(", s1 = {} is valid", s1); - // } - tmp.push(s1); - } - let mut s2 = s.and(Condition::Operational); - if s2.check_constraints(&self.damaged_spring_groups, true, false) { - // if cfg!(test) { - // print!(", s2 = {} is valid", s2); - // } - tmp.push(s2); - } - tmp - }, - c => { - // if cfg!(test) { - // print!(": definite"); - // } - let mut s1 = s.and(*c); - if s1.check_constraints(&self.damaged_spring_groups, true, false) { - // if cfg!(test) { - // print!(", s1 = {} is valid", s1); - // } - vec![s1] - } else { - vec![] - } - } - }; - // if cfg!(test) { - // println!(); - // } - new_states - }).collect(); - // println!(" ... next_states = {}", next_states.iter().map(|s| self.format_state(s)).collect::>().join(",")); + for (i, c) in self.conditions.iter().enumerate() { + let next_states = &states + .drain(..) + .flat_map(|s| self.process_state(s, *c)) + .collect::>(); if next_states.is_empty() { println!("no more states, can return empty early"); return vec![]; } - *states = next_states; + *states = next_states.to_vec(); + if print { + println!("{}/{} |states| = {:?}", i, self.conditions.len(), states.len()); + } } // Filter out the invalid states @@ -272,6 +256,10 @@ impl ConditionRecord { // println!("state = {}: pruned, invalid at full", s); } } + + if print { + println!("|result| = {:?}", result.len()); + } result } @@ -291,32 +279,23 @@ impl ConditionRecord { let initial_state = vec![]; states.push(initial_state); for c in &self.conditions { - // println!("{:?} with states {}", c, states.iter().map(|s| Self::format_state(s)).collect::>().join(",")); - // Modify the states depending on the condition // If we see a '.' or '#' then it will be added immediately to the states, which may // make some switch from "could work" to "invalid". // If we see a '?' we fork the state, and keep the the valid parts. let next_states: Vec<_> = states.iter().flat_map(|s| { - // println!(" ... looking at {}{}", Self::format_state(s), *c as u8 as char); match c { Condition::Unknown => { let mut tmp = vec![]; let mut s1 = s.clone(); s1.push(Condition::Damaged); - if self.violates_constraints(&s1, true) { - // println!(" ... {:?} violates constraints", Self::format_state(&s1)); - } else { - // println!(" ... {:?} is acceptable", Self::format_state(&s1)); + if !self.violates_constraints(&s1, true) { tmp.push(s1); } let mut s2 = s.clone(); s2.push(Condition::Operational); - if self.violates_constraints(&s2, true) { - // println!(" ... {:?} violates constraints", Self::format_state(&s2)); - } else { - // println!(" ... {:?} is acceptable", Self::format_state(&s2)); + if !self.violates_constraints(&s2, true) { tmp.push(s2); } tmp @@ -324,16 +303,14 @@ impl ConditionRecord { _ => { let mut s1 = s.clone(); s1.push(*c); - if self.violates_constraints(&s1, true) { - // println!(" ... {:?} violates constraints", Self::format_state(&s1)); - vec![] - } else { + if !self.violates_constraints(&s1, true) { vec![s1] + } else { + vec![] } } } }).collect(); - // println!(" ... next_states = {}", next_states.iter().map(|s| self.format_state(s)).collect::>().join(",")); if next_states.is_empty() { println!("no more states, can return 0 early"); return 0; @@ -527,7 +504,7 @@ mod tests { fn part1_tests() { //assert_eq!("???.#??#.??? 1,1,2,1".parse::().unwrap().num_arrangements(), 10); let cr = "##???#??#?????????#? 11,6".parse::().unwrap(); - assert_eq!(cr.arrangements(), &[ + assert_eq!(cr.arrangements(false), &[ "###########..######.", "###########...######", ]); From 0065021cc4cad5e3b241911536a91ca1f8148b9a Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 16:20:48 +0100 Subject: [PATCH 101/120] More debug printing in the process_state parts --- src/day12.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index b7efb43..37ab1f9 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -198,23 +198,29 @@ impl ConditionRecord { self.arrangements(false).len() } - fn process_state(&self, s: State, c: Condition) -> Vec { + fn process_state(&self, s: State, c: Condition, print: bool) -> Vec { let mut result = vec![]; match c { Condition::Unknown => { let mut s1 = s.and(Condition::Damaged); if s1.check_constraints(&self.damaged_spring_groups, true, false) { result.push(s1); + } else if print { + println!("... {} dropped", s1); } let mut s2 = s.and(Condition::Operational); if s2.check_constraints(&self.damaged_spring_groups, true, false) { result.push(s2); + } else if print { + println!("... {} dropped", s2); } }, c => { let mut s1 = s.and(c); if s1.check_constraints(&self.damaged_spring_groups, true, false) { result.push(s1); + } else if print { + println!("... {} dropped", s1); } } } @@ -232,7 +238,7 @@ impl ConditionRecord { for (i, c) in self.conditions.iter().enumerate() { let next_states = &states .drain(..) - .flat_map(|s| self.process_state(s, *c)) + .flat_map(|s| self.process_state(s, *c, print)) .collect::>(); if next_states.is_empty() { println!("no more states, can return empty early"); From 583e79f25dc5b008fc9644f51838c3dc572b0149 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 16:51:02 +0100 Subject: [PATCH 102/120] Move the processing of the repetition closer to the main logic We need to massively reduce the number of open states, start by refactoring so that `arrangements` is aware of the repeat factor. --- src/day12.rs | 102 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index 37ab1f9..df137c1 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -175,41 +175,34 @@ impl Display for State { struct ConditionRecord { conditions: Vec, damaged_spring_groups: Vec, + repeat: usize, } impl ConditionRecord { pub fn repeat(&self, n: usize) -> ConditionRecord { - let mut new_conditions = vec![]; - for i in 0..n { - for c in &self.conditions { - new_conditions.push(*c); - } - if i != n-1 { - new_conditions.push(Condition::Unknown); - } - } ConditionRecord { - conditions: new_conditions, - damaged_spring_groups: self.damaged_spring_groups.repeat(n), + conditions: self.conditions.clone(), + damaged_spring_groups: self.damaged_spring_groups.clone(), + repeat: self.repeat * n, } } pub fn num_arrangements(&self) -> usize { - self.arrangements(false).len() + Self::arrangements(&self.conditions, &self.damaged_spring_groups, self.repeat, false).len() } - fn process_state(&self, s: State, c: Condition, print: bool) -> Vec { + fn process_state(damaged_spring_groups: &[usize], s: State, c: Condition, print: bool) -> Vec { let mut result = vec![]; match c { Condition::Unknown => { let mut s1 = s.and(Condition::Damaged); - if s1.check_constraints(&self.damaged_spring_groups, true, false) { + if s1.check_constraints(damaged_spring_groups, true, false) { result.push(s1); } else if print { println!("... {} dropped", s1); } let mut s2 = s.and(Condition::Operational); - if s2.check_constraints(&self.damaged_spring_groups, true, false) { + if s2.check_constraints(damaged_spring_groups, true, false) { result.push(s2); } else if print { println!("... {} dropped", s2); @@ -217,7 +210,7 @@ impl ConditionRecord { }, c => { let mut s1 = s.and(c); - if s1.check_constraints(&self.damaged_spring_groups, true, false) { + if s1.check_constraints(damaged_spring_groups, true, false) { result.push(s1); } else if print { println!("... {} dropped", s1); @@ -227,33 +220,55 @@ impl ConditionRecord { result } - fn arrangements(&self, print: bool) -> Vec { + fn arrangements(conditions: &[Condition], damaged_spring_groups: &[usize], repeat: usize, print: bool) -> Vec { // Stupid logic: Each '?' can be either '.' or '#'. So, try both, and then proceed // and see if _at the end_. Essentially we're building a matching automaton here?????!?!?!! // Each state is the conditions we found. let states: &mut Vec = &mut vec![]; + let repeated_damaged_spring_groups = damaged_spring_groups.repeat(repeat); // Start out with one empty state: states.push(State::empty()); - for (i, c) in self.conditions.iter().enumerate() { - let next_states = &states - .drain(..) - .flat_map(|s| self.process_state(s, *c, print)) - .collect::>(); - if next_states.is_empty() { - println!("no more states, can return empty early"); - return vec![]; + for r in 0..repeat { + for (i, c) in conditions.iter().enumerate() { + let next_states = &states + .drain(..) + .flat_map(|s| Self::process_state(&repeated_damaged_spring_groups, s, *c, print)) + .collect::>(); + if next_states.is_empty() { + println!("no more states, can return empty early"); + return vec![]; + } + *states = next_states.to_vec(); + if print { + println!("{}/{}: {}/{} |states| = {:?}", r, repeat, i, conditions.len(), states.len()); + } } - *states = next_states.to_vec(); - if print { - println!("{}/{} |states| = {:?}", i, self.conditions.len(), states.len()); + + // Repeating adds a unknown condition, so process that. + if r != repeat-1 { + if print { + println!("{}/{}: processing implicit unknown condition", r, repeat); + } + let next_states = &states + .drain(..) + .flat_map(|s| Self::process_state(&repeated_damaged_spring_groups, s, Condition::Unknown, print)) + .collect::>(); + if next_states.is_empty() { + println!("no more states, can return empty early"); + return vec![]; + } + *states = next_states.to_vec(); + if print { + println!("{}/{}: |states after repeat| = {:?}", r, repeat, states.len()); + } } } // Filter out the invalid states let mut result = vec![]; for s in states.iter_mut() { - let valid = s.check_constraints(&self.damaged_spring_groups, false, false); + let valid = s.check_constraints(&repeated_damaged_spring_groups, false, false); if valid { // println!("state = {}: counted, valid at full", s); let cond_str = std::str::from_utf8(&s.conditions.iter().map(|c| *c as u8).collect::>()).unwrap().to_string(); @@ -388,6 +403,7 @@ impl std::str::FromStr for ConditionRecord { Ok(ConditionRecord { conditions: ConditionRecord::parse_state(p), damaged_spring_groups, + repeat: 1, }) } else { Err("cannot parse damaged spring groups") @@ -510,7 +526,7 @@ mod tests { fn part1_tests() { //assert_eq!("???.#??#.??? 1,1,2,1".parse::().unwrap().num_arrangements(), 10); let cr = "##???#??#?????????#? 11,6".parse::().unwrap(); - assert_eq!(cr.arrangements(false), &[ + assert_eq!(ConditionRecord::arrangements(&cr.conditions, &cr.damaged_spring_groups, 1, false), &[ "###########..######.", "###########...######", ]); @@ -519,14 +535,7 @@ mod tests { #[test] fn condition_record_repeat() { let cr = ".# 1".parse::().unwrap().repeat(2); - assert_eq!(cr.conditions, vec![ - Condition::Operational, - Condition::Damaged, - Condition::Unknown, - Condition::Operational, - Condition::Damaged, - ]); - assert_eq!(cr.damaged_spring_groups, vec![1,1]); + assert_eq!(cr.repeat, 2); } #[test] @@ -541,6 +550,23 @@ mod tests { assert_eq!(num_arrangements(DATA, 5), 525152) } + #[test] + fn part2_tests_known() { + let cr = "???.### 1,1,3".parse::().unwrap(); + for line in ConditionRecord::arrangements(&cr.conditions, &cr.damaged_spring_groups, 5, true) { + println!("{}", line); + } + } + + #[test] + fn part2_tests_dump() { + // let cr = "???.#??#.??? 1,1,2,1".parse::().unwrap(); + let cr = "????.######..#####. 1,6,5".parse::().unwrap(); + for line in ConditionRecord::arrangements(&cr.conditions, &cr.damaged_spring_groups, 2, true) { + println!("{}", line); + } + } + #[test] fn old_vs_new() { match std::fs::read_to_string("day12.input") { From 09e982c9d629c9b6088b9174f17daae7e8eb6572 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 17:12:55 +0100 Subject: [PATCH 103/120] Add some experimental early pruning of states after each repetition This is a probably-wrong thing to do, but it should help to see by how much we need to reduce to make this viable. --- src/day12.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index df137c1..b9042b7 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -258,9 +258,22 @@ impl ConditionRecord { println!("no more states, can return empty early"); return vec![]; } - *states = next_states.to_vec(); - if print { - println!("{}/{}: |states after repeat| = {:?}", r, repeat, states.len()); + + // Prune everything that doesn't have at least a remote chance: We should have roughly + // the same number of groups in this section than existed in the original damaged_spring_groups. + states.clear(); + for s in next_states { + // XXX: This is probably the same or related-to as last_damaged_group_index. + // XXX: The problem is that we may have situations where the added Unknown actually makes some group + // possible -- but I don't see yet how. + let expected_num_groups = damaged_spring_groups.len() * (r + 1); + if s.last_damaged_spring_groups_index >= expected_num_groups - 1 { + states.push(s.clone()); + } + } + + if true || print { + println!("{}/{}: |states after repeat| = {:?}, dropped = {}", r, repeat, states.len(), next_states.len() - states.len()); } } } From f50f082422c07900b18915c239ecce303dbde4e3 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 18:58:16 +0100 Subject: [PATCH 104/120] Multithread the whole thing This doesn't really help a lot, except actually making use of the CPUs as a heater. --- src/day12.rs | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index b9042b7..e99e075 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -272,7 +272,7 @@ impl ConditionRecord { } } - if true || print { + if print { println!("{}/{}: |states after repeat| = {:?}, dropped = {}", r, repeat, states.len(), next_states.len() - states.len()); } } @@ -411,7 +411,7 @@ impl std::str::FromStr for ConditionRecord { fn from_str(s: &str) -> Result { if let Some((p, g)) = s.split_once(' ') { - println!("from_str: p='{}', g='{}'", p, g); + // println!("from_str: p='{}', g='{}'", p, g); if let Ok(damaged_spring_groups) = g.split(',').map(usize::from_str).collect::, _>>() { Ok(ConditionRecord { conditions: ConditionRecord::parse_state(p), @@ -428,13 +428,47 @@ impl std::str::FromStr for ConditionRecord { } fn num_arrangements(input: &str, repeat: usize) -> usize { - input.split('\n').map(str::parse::).map(|cr| cr.unwrap().repeat(repeat).num_arrangements()).sum() + let thread_count_arc = std::sync::Arc::new((std::sync::Mutex::new(0u8), std::sync::Condvar::new())); + + let mut v = vec![]; + for (id, line) in input.split('\n').enumerate() { + if let Ok(cr) = line.parse::() { + let thread_count = thread_count_arc.clone(); + let jh = std::thread::spawn(move || { + let (num, cvar) = &*thread_count; + + let mut start = cvar + .wait_while(num.lock().unwrap(), |start| *start >= 32) + .unwrap(); + *start += 1; + drop(start); + + println!("thread {} for \"{}\" running", id, cr.conditions.iter().map(|c| *c as u8 as char).collect::()); + let result = cr.repeat(repeat).num_arrangements(); + println!("thread {} for \"{}\" finished: {} arrangements", id, cr.conditions.iter().map(|c| *c as u8 as char).collect::(), result); + + start = num.lock().unwrap(); + *start -= 1; + cvar.notify_one(); + + result + }); + v.push(jh); + } + } + + let expected = v.len(); + v.drain(..).enumerate().map(|(i, jh)| { + let result = jh.join().unwrap(); + println!("joined {}, {} total", i, expected); + result + }).sum() } pub fn main() { match std::fs::read_to_string("day12.input") { Ok(input) => { - println!("num_arrangements = {}", num_arrangements(&input, 1)); + // println!("num_arrangements = {}", num_arrangements(&input, 1)); println!("num_arrangements (part 2) = {}", num_arrangements(&input, 5)); }, Err(reason) => println!("error = {}", reason) From b45eeaa653c4b9ccbead2014250dea2fb068f1c8 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 19:53:05 +0100 Subject: [PATCH 105/120] Collapse similar states to reduce the processing effort Ultimately it doesn't matter for the world if we're looking at `#..#..#` or `#.#...#`, they are identical in terms of the distribution of the groups, and therefore for the number of arrangements. By collapsing these states into each other regularly, and only keeping track of how many we collapsed, the processing time needed goes down from "days" to "seconds". Multithreading is still left in place, because it will be a good example to steal later, but the initial attempt of pruning was now completely useless and got removed. --- src/day12.rs | 185 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 142 insertions(+), 43 deletions(-) diff --git a/src/day12.rs b/src/day12.rs index e99e075..bf88b43 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] enum Condition { Operational = '.' as isize, Damaged = '#' as isize, @@ -29,13 +29,18 @@ impl Display for Condition { } // State when searching for arrangements -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq)] struct State { conditions: Vec, unchecked_condition: Option, last_damaged_count: usize, last_damaged_spring_groups_index: usize, invalid: bool, + + // Number of states that collapsed into this one because + // they had the same last_damaged_spring_groups_index, last_damaged_count and + // last condition. + num_similar: usize, } impl State { @@ -46,6 +51,7 @@ impl State { last_damaged_count: 0, last_damaged_spring_groups_index: 0, invalid: false, + num_similar: 0, } } fn and(&self, c: Condition) -> State { @@ -61,6 +67,7 @@ impl State { last_damaged_count: self.last_damaged_count, last_damaged_spring_groups_index: self.last_damaged_spring_groups_index, invalid: false, + num_similar: self.num_similar, } } @@ -160,7 +167,7 @@ impl State { impl Display for State { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let cond_str = std::str::from_utf8(&self.conditions.iter().map(|c| *c as u8).collect::>()).unwrap().to_string(); - let r = write!(f, "\"{}\" (ldc = {}, i = {}, invalid = {}", cond_str, self.last_damaged_count, self.last_damaged_spring_groups_index, self.invalid); + let r = write!(f, "\"{}\" (ldc = {}, i = {}, invalid = {}, similar = {}", cond_str, self.last_damaged_count, self.last_damaged_spring_groups_index, self.invalid, self.num_similar); if r.is_err() { panic!("cannot format state"); } @@ -172,6 +179,80 @@ impl Display for State { } } +impl std::cmp::PartialEq for State { + fn eq(&self, other: &Self) -> bool { + if self.unchecked_condition.is_some() || other.unchecked_condition.is_some() { + panic!("cannot compare states with unchecked conditions"); + } + + // Easy things: + if self.invalid != other.invalid { + return false; + } + if self.conditions.len() != other.conditions.len() { + return false; + } + if self.last_damaged_count != other.last_damaged_count { + return false; + } + if self.last_damaged_spring_groups_index != other.last_damaged_spring_groups_index { + return false; + } + + // Last condition must be the same: + match (self.conditions.last(), other.conditions.last()) { + (Some(last), Some(other_last)) => { + if last != other_last { + return false; + } + }, + (None, None) => {}, + _ => return false, + } + + // NB: We're not comparing num_similar, as that is just an internal + // multiplier. + true + } +} + +impl std::cmp::PartialOrd for State { + fn partial_cmp(&self, other: &Self) -> Option { + if self.unchecked_condition.is_some() || other.unchecked_condition.is_some() { + panic!("cannot compare states with unchecked conditions"); + } + + // First: Compare the parts we also use in the partial equality checks. + match self.invalid.partial_cmp(&other.invalid) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + match self.conditions.len().partial_cmp(&other.conditions.len()) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + match self.last_damaged_count.partial_cmp(&other.last_damaged_count) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + match self.last_damaged_spring_groups_index.partial_cmp(&other.last_damaged_spring_groups_index) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + match self.conditions.last().partial_cmp(&other.conditions.last()) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + + // Rest "just" needs to be sane enough. + match self.conditions.partial_cmp(&other.conditions) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + self.num_similar.partial_cmp(&other.num_similar) + } +} + struct ConditionRecord { conditions: Vec, damaged_spring_groups: Vec, @@ -188,7 +269,7 @@ impl ConditionRecord { } pub fn num_arrangements(&self) -> usize { - Self::arrangements(&self.conditions, &self.damaged_spring_groups, self.repeat, false).len() + Self::arrangements(&self.conditions, &self.damaged_spring_groups, self.repeat, false).drain(..).fold(0, |acc, s| acc + s.num_similar + 1) } fn process_state(damaged_spring_groups: &[usize], s: State, c: Condition, print: bool) -> Vec { @@ -220,7 +301,7 @@ impl ConditionRecord { result } - fn arrangements(conditions: &[Condition], damaged_spring_groups: &[usize], repeat: usize, print: bool) -> Vec { + fn arrangements(conditions: &[Condition], damaged_spring_groups: &[usize], repeat: usize, print: bool) -> Vec { // Stupid logic: Each '?' can be either '.' or '#'. So, try both, and then proceed // and see if _at the end_. Essentially we're building a matching automaton here?????!?!?!! // Each state is the conditions we found. @@ -231,18 +312,39 @@ impl ConditionRecord { states.push(State::empty()); for r in 0..repeat { for (i, c) in conditions.iter().enumerate() { - let next_states = &states + let next_states = &mut states .drain(..) .flat_map(|s| Self::process_state(&repeated_damaged_spring_groups, s, *c, print)) .collect::>(); - if next_states.is_empty() { - println!("no more states, can return empty early"); - return vec![]; - } - *states = next_states.to_vec(); + + let next_states_len = next_states.len(); + + // Collapse states: Sort them, then drop equal ones and bump the num_similar counter. At the + // end we just count these counters when summing up. + states.sort_by(|a, b| a.partial_cmp(b).unwrap()); + let collapsed_states = &next_states + .drain(..) + .fold(vec![], |mut acc: Vec, s| { + if let Some(last) = acc.last_mut() { + if *last == s { + last.num_similar += s.num_similar + 1; + if print { + println!("... {} collapsed into {}", s, last); + } + } else { + acc.push(s); + } + } else { + acc.push(s); + } + acc + }); + if print { - println!("{}/{}: {}/{} |states| = {:?}", r, repeat, i, conditions.len(), states.len()); + println!("{}/{}: {}/{} |next_states| = {:?}, |collapsed_states| = {:?}", r, repeat, i, conditions.len(), next_states_len, collapsed_states.len()); } + + *states = collapsed_states.to_vec(); } // Repeating adds a unknown condition, so process that. @@ -254,47 +356,34 @@ impl ConditionRecord { .drain(..) .flat_map(|s| Self::process_state(&repeated_damaged_spring_groups, s, Condition::Unknown, print)) .collect::>(); - if next_states.is_empty() { - println!("no more states, can return empty early"); - return vec![]; - } - // Prune everything that doesn't have at least a remote chance: We should have roughly - // the same number of groups in this section than existed in the original damaged_spring_groups. - states.clear(); - for s in next_states { - // XXX: This is probably the same or related-to as last_damaged_group_index. - // XXX: The problem is that we may have situations where the added Unknown actually makes some group - // possible -- but I don't see yet how. - let expected_num_groups = damaged_spring_groups.len() * (r + 1); - if s.last_damaged_spring_groups_index >= expected_num_groups - 1 { - states.push(s.clone()); - } - } + // We could do the collapsing here, but it will happen in the next iteration anyways + // and shouldn't cost too much as we already did it just above. + *states = next_states.to_vec(); + } - if print { - println!("{}/{}: |states after repeat| = {:?}, dropped = {}", r, repeat, states.len(), next_states.len() - states.len()); - } + if states.is_empty() { + println!("no more states, can return empty early"); + return vec![]; } } // Filter out the invalid states - let mut result = vec![]; + let mut final_states = vec![]; for s in states.iter_mut() { let valid = s.check_constraints(&repeated_damaged_spring_groups, false, false); if valid { // println!("state = {}: counted, valid at full", s); - let cond_str = std::str::from_utf8(&s.conditions.iter().map(|c| *c as u8).collect::>()).unwrap().to_string(); - result.push(cond_str); + final_states.push(s.to_owned()); } else { // println!("state = {}: pruned, invalid at full", s); } } if print { - println!("|result| = {:?}", result.len()); + println!("|result| = {:?}", final_states); } - result + final_states } fn parse_state(s: &str) -> Vec { @@ -427,7 +516,7 @@ impl std::str::FromStr for ConditionRecord { } } -fn num_arrangements(input: &str, repeat: usize) -> usize { +fn num_arrangements(input: &str, repeat: usize, concurrent: u8) -> usize { let thread_count_arc = std::sync::Arc::new((std::sync::Mutex::new(0u8), std::sync::Condvar::new())); let mut v = vec![]; @@ -438,7 +527,7 @@ fn num_arrangements(input: &str, repeat: usize) -> usize { let (num, cvar) = &*thread_count; let mut start = cvar - .wait_while(num.lock().unwrap(), |start| *start >= 32) + .wait_while(num.lock().unwrap(), |start| *start >= concurrent) .unwrap(); *start += 1; drop(start); @@ -469,7 +558,7 @@ pub fn main() { match std::fs::read_to_string("day12.input") { Ok(input) => { // println!("num_arrangements = {}", num_arrangements(&input, 1)); - println!("num_arrangements (part 2) = {}", num_arrangements(&input, 5)); + println!("num_arrangements (part 2) = {}", num_arrangements(&input, 5, 32)); }, Err(reason) => println!("error = {}", reason) } @@ -566,17 +655,17 @@ mod tests { assert_eq!("????.######..#####. 1,6,5".parse::().unwrap().num_arrangements(), 4); assert_eq!("?###???????? 3,2,1".parse::().unwrap().num_arrangements(), 10); - assert_eq!(num_arrangements(DATA, 1), 21) + assert_eq!(num_arrangements(DATA, 1, 1), 21) } #[test] fn part1_tests() { //assert_eq!("???.#??#.??? 1,1,2,1".parse::().unwrap().num_arrangements(), 10); let cr = "##???#??#?????????#? 11,6".parse::().unwrap(); - assert_eq!(ConditionRecord::arrangements(&cr.conditions, &cr.damaged_spring_groups, 1, false), &[ + assert_eq!(ConditionRecord::arrangements(&cr.conditions, &cr.damaged_spring_groups, 1, false).len(), [ "###########..######.", "###########...######", - ]); + ].len()); } #[test] @@ -594,7 +683,17 @@ mod tests { assert_eq!("????.######..#####. 1,6,5".parse::().unwrap().repeat(5).num_arrangements(), 2500); assert_eq!("?###???????? 3,2,1".parse::().unwrap().repeat(5).num_arrangements(), 506250); - assert_eq!(num_arrangements(DATA, 5), 525152) + assert_eq!(num_arrangements(DATA, 5, 1), 525152) + } + + #[test] + fn part2_simple() { + let cr = "????.#...#... 4,1,1".parse::().unwrap(); + let states = ConditionRecord::arrangements(&cr.conditions, &cr.damaged_spring_groups, 5, true); + for s in &states { + println!("state = {}", s); + } + assert_eq!(states.iter().fold(0, |acc, s| acc + s.num_similar + 1), 16); } #[test] From 74544a2bb18c1de08544a5fae8eae0f295628dd8 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 21:31:48 +0100 Subject: [PATCH 106/120] Day 13, part 1: In principle this works ... but in practice? --- day13.input | 1349 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/day13.rs | 318 ++++++++++++ src/main.rs | 4 +- 3 files changed, 1669 insertions(+), 2 deletions(-) create mode 100644 day13.input create mode 100644 src/day13.rs diff --git a/day13.input b/day13.input new file mode 100644 index 0000000..37e0186 --- /dev/null +++ b/day13.input @@ -0,0 +1,1349 @@ +...##.... +.#.##.#.. +.#....#.. +.##..##.. +...##.... +..####.## +#..##..## + +##...##.. +.##.#..#. +.#....... +...#.##.# +##..#..#. +.##..##.. +.#...##.. +#.####### +....####. +..##.##.# +..##.##.# +....####. +#.####### +.#...##.. +.##..##.. +#...#..#. +...#.##.# + +...#...##...### +##.#.##.#..#.## +####.##.#..#.## +#.#.##.###.#.## +#...##.##...#.# +##..#.###...#.. +#...####.###... +#.#####...##.## +#.#####...##.## +#...####.###... +##..#.###...#.. +#...##.##...#.# +#.#.##.###.#.## +####.##.#..#.## +##.#.##.#..#.## + +.....#. +###.### +##.#.## +..#..## +..###.. +..###.. +..#..## +##.#.## +###.### +.....## +###..#. +..#..## +##.#### + +....#....##.... +.##..##.####.## +#..#.#...##...# +.##.####....### +#..#.##.####.## +#..###.#.##.#.# +.##.##.##..#### + +..##..##..#.#.# +.####......#.#. +.#.#.###...#..# +.##.#..##.....# +..#.#.##..###.# +..#.#.##..###.# +.##.#..##.....# +.#.#.###...#..# +.####......#.#. +..##..##..#.#.# +#...#..#...#... +.#.#.##..##...# +.#.#.##..###..# + +#...##...#.#.##.# +#...##...#.#.#### +#.##..##.##.##.#. +............###.# +....##.....###.## +#..#..#..#.##.... +#.#....#.#..##.## +..######...####.# +#.#....#.#..##### +.#.####.#.#.###.. +.##.##.##..#...## + +##.##....##.##... +##....##....##.## +#.##..##..##.##.. +.##.#.##.#.##.#.. +..##.....###...## +####.#..#.####.## +.#..........#.... +#####.##.######.. +#..#.####.#..#... + +#.##..###.#.. +.#...###...#. +##...####.... +####..#.#.#.. +#.....##..### +#.....##..### +####..#.#.#.. +##...####..#. +.#...###...#. +#.##..###.#.. +###.#.####..# +.##.#.#...### +#.##.######.# +#..#.......#. +#..#.......#. + +###...##...## +...#..#####.# +###.##.#..... +..#...#...### +..##.###..... +....#...#...# +#####...##.## +....#.##.#### +....#.##.##.# + +..##..###...#.... +##..#######...### +##..###.......#.# +..##..#.#....#### +########...###... +.####........#... +.####.#..##...### +.#..#...###.#.### +.####.#.###.##... +#.##.#..####.#... +#.##.#..##...#... + +#.#....#.## +..#....#... +..#....#... +#.#....#.## +##......##. +.#.####.#.. +####.#####. + +...##...#..#. +########...#. +.######..#... +..#..#.....## +#.#..#.#####. +##....##.#### +..####...###. +#.#..#.##.#.# +#......#.###. +.#.##.#.####. +.#.##.#.####. +#......#.###. +#.#..#.#..#.# + +##....#.##.##.##. +####......#..#... +#...###..######.. +#...#.##..#..#..# +.#.##.#.########. +.#.##.#.########. +....#.##..#..#..# + +###..##.# +##.#..##. +##..#.... +....#.... +..#...... +..##..##. +##.#.#..# + +.....#...#. +..##...#... +##..###...# +.#..#.#.### +#.##.#.##.. +.#..#.##.## +#######.##. +.........## +..##....#.# +.......#..# +.#..#.####. +#....#####. +#.##.#..#.# +#.##.#..#.# +#....#####. +.#..#.####. +.......#..# + +#.####. +#.####. +...#... +##...## +....#.. +#....#. +.#..#.. +#..#.## +#.#.... +.#..#.# +.#..#.# +#.#...# +#..#.## + +.##..##..#.## +#..#..#..#.## +....####.#### +....###.##.## +.####..##.### +.....#...#.## +#..##.##...## +####.###..... +.##..#....### +#..#..#..#### +.##.#####.#.. +......###.### +#..#####..#.. +#..##.....### +#..#..#.#..## + +.###..##..### +.#.#.#..#.#.# +....##..##... +....##..##... +##.#.#..#.#.# +.###..##..### +###.#....#.## + +##.########.##. +###.#.#..#.#### +..#...##...#..# +###.##..##.###. +#.#.##..##.#.#. +.##.#.##.#.##.# +.##.#.##.#.##.# + +.#..##. +..#..## +###.### +###.### +..#..## +.#..##. +.#.##.. +#...##. +#...##. +.#.##.. +.#..##. +#.#..## +###.### + +......#.#.#.# +......#.#.#.# +#..##...##..# +#..##..##..#. +..#.##.##.##. +#..##..#..#.# +#..#.#..##### +#..#.##.##..# +....####..##. +.##..#..##.#. +####.#...##.. +.....#.####.# +#..#....###.. + +.#...#.#...##.. +#....#.#....... +..##.#.....##.. +####.###..####. +.#.#.#...#..... +##...###....... +..##.#.######## +.####.....#..#. +.#.#..##....... +##.#..#.##.##.# +..#....#.#....# +..#....#.#....# +##.#..#.##.##.# +.#.#..##....... +.####.....#..#. +..##.#.######## +##...###....... + +.......#.#.#### +.......#.#.#### +..##..####.##.# +#...####.####.# +##..##.####.##. +#....##.#.###.. +.####..#...#.#. +#.##.#.##.##..# +..##.......#.#. +#....##..#..#.# +..##...##..##.# +#######.#....## +#.##.#..##.#.#. + +....##..# +..#.##..# +..#.###.# +#......## +...##.... +.##..#.#. +#.#.#.... +#..#....# +.##.###.. +###.#.##. +###.#.##. + +######. +.###... +##.##.# +#..##.. +#..##.. +##.##.# +.###... +######. +...#... +..##.## +##...## +##....# +..##.## +...#... +######. +.###... +##.##.# + +....###.#.. +.##.##.#### +.##.##.#### +....#####.. +######.#..# +#####..#.#. +....##...#. +.##.##.#..# +.##.##..#.# +#..#.#.#.## +.##..###.## +....###...# +.##.##.#... +####.#.#.#. +#..#.##..#. + +##..#.##.#.#..#.. +..#....#..##.##.# +...##...####..### +###..#.#..#.##.## +###..#....#.##.## +...##...####..### +..#....#..##.##.# +##..#.##.#.#..#.. +..#.##..#.#..#..# +..##..#...#....## +..####..##.....## + +.......####..#..# +.##.#....###..##. +###..#.###.###..# +##.##...######### +....###......#..# +.#.########...##. +#.......###.####. +#...##..##.##.##. +#.#.#.#....#..... +##....###..###..# +..#.##.###.#.#### +..#.##.###.#.#### +##....###..###..# +#.#.#.#....#..... +#...##..##.##.##. + +###..## +..#.#.# +####.#. +...#..# +##.#..# +##.#.## +...#..# +####.#. +..#.#.# + +####... +...##.. +###..## +##.###. +##.###. +###..## +...##.. +####... +#.##... +....#.. +##..### + +.###...## +.###...## +.##.##.#. +....##..# +##.###.#. +.#..##..# +###.#..## +#.#.####. +#.#.####. +###.#..## +.#...#..# +##.###.#. +....##..# +.##.##.#. +.###...## + +#.##.##.#..#.##.# +..##.##.####.##.# +#.############### +..#.............. +#.#..##......##.. +.#.##..##..##..## +#........##...... +##.#..#.#..#.#..# +....####....####. +#....##......##.. +...#.##.#..#.##.# +##..####.##.####. +#..#....#..#....# +.#..#..#.##.#..#. +.....##......##.. + +.#....#.#...##... +.#.##.#..#.####.# +#..##..#.#.#..#.# +##.##.##..##..##. +###..######.##.## +########.#.#..#.# +...##...#..####.. +#......#.#......# +.##..##...##..### + +..##.#.#.##.#.# +..##.#.#.##.#.# +##..#....##.### +...#..#.#..#... +.#.####..####.. +..##.##..####.# +##....#.##.#.#. +...#.#...#####. +...#.#####...#. +###...#..###..# +..........###.. + +##....##....##. +##....##....##. +#.#.#....#.#.#. +##..##...#..##. +####......####. +#.#...##...#.## +.#####..#####.. + +......###.. +.#..#.####. +.#..#.###.. +.####...### +.####...### +.#..#.###.. +.#..#.####. +......###.. +..##..##... +##..###..## +.####...#.. +##..###.#.# +..##...##.. +##..#####.# +###.##.#... + +......##.#.#. +.#.....#...#. +###.#..#...## +#..#.##.#...# +#..#.####...# +###.#..#...## +.#.....#...#. +......##.#.#. +##.######...# +...#...##.### +#....#####..# +..##..#..##.# +#.####..#.### +.##...###.#.. +.#..#.###.##. +.#..#.###.##. +.##...###.#.. + +.###..###.##. +###.###..#.#. +..###......#. +#..#..#.#...# +.#..#.....#.# +.#.#...##.#.# +##...##..##.# +##...##..##.# +.#.#...##.#.# +.#.##.....#.# +#..#..#.#...# +..###......#. +###.###..#.#. +.###..###.##. +.###..###.##. + +###.####.## +##........# +#.......... +#.########. +..##....##. +.#.#.##.#.# +.#........# +#.........# +.##......## +###..##..## +#####..#### +#####..#### +###..##..## + +##.#.#..#.. +....#...##. +##..#.#..#. +...######.. +#######..## +##.##..#.## +..#..####.# +###...##... +......##.#. +###.#..#..# +..##..###.. +...#.#.##.# +...#.#.##.# +..##.####.. +###.#..#..# +......##.#. +###...##... + +#####.#.##...#. +......######... +#...#.#.#.#..## +..####.#.#.##.# +..######.#.##.# +#...#.#.#.#..## +......######... +#####.#.##...#. +.#...##..###... +.#...##..###... +#####.#.##...#. + +####.#. +#..#### +#..#..# +#..#..# +.##.#.. +.##..## +...#..# +....##. +#..#### +#..#### +....##. + +###...##.###...## +###.####...####.# +...#..#.##.#.##.. +...#..#.##.#.##.. +###.####...####.# +###...##.###...## +.#.#.#.##.#....## +.#.#.#.##.#....## +###...##.#.#...## + +.##.....# +........# +#####..#. +#####..#. +####..### +....##... +....####. +#..###..# +.##..##.# +.##..##.# +#..###..# +....###.. +....##... +####..### +#####..#. +#####..#. +........# + +.#...## +.#...## +##..... +.#.#### +##.##.. +#....#. +.####.. +#....#. +#....#. +.####.# +#....#. +##.##.. +.#.#### + +..#.#.##... +..#.#.###.. +##.##..###. +..####...#. +##.#....### +.#...#####. +..#.##.###. +.#....##... +.#..#.##..# +.#..#.##..# +.#....##... +..#.##.###. +.#...#####. +##.#....### +..####...#. + +####.#####....# +#..#.###..#..#. +####.####....## +#######..###.## +#..###..##....# +.##..###.#...## +.##..###.#...## +#..###..##....# +#####.#..###.## +####.####....## +#..#.###..#..#. +####.#####....# +.##.####.##.#.# + +####.## +..##.#. +..##... +.#..... +....##. +##..#.# +###...# +##.##.# +..##... +..##... +##.##.# + +#.#.#.#.....##... +..#...#...#....#. +.##..##..##.##.## +...#.##.##......# +###..##.#.#.##.#. +.##.####..#....#. +.###..##......... +..#.###..#.####.# +.#...#.#..#.##.#. +###...######..### +#.#####...######. +###.###.#..####.. +##..##.###..#...# +##..#..##.######. +##..#..##.######. + +.###.#..#.###..## +####.#..#.####### +.##..#..#..#....# +##.#.####.#.####. +...#......#...... +....#....#....... +......##......... +#.##..##..##.##.# +.##.######.##..## + +...######...#.# +...######...#.# +..###..###....# +.##.####.##..## +.#.######.#.... +###.#..#.##..## +#.#..##..#.###. +.##......##.### +###.####.###.## +.#..####..#...# +.###.##.###.### +##.######.###.# +#..##..##..#.#. + +....##.....##..## +.##.##.##..#....# +..#....#.....##.. +.##.##.##..#....# +##########....... +###########.####. +..#.##.#..#.#..#. +#..####..###....# +..##..##......... +..##..##...###### +#........#.#....# +#.######.####..## +.###..###..#.##.# +.##....##...#..#. +....##...#.#.##.# + +.##...#..#### +.....####..## +#######.#..#. +#..###.#.###. +#..#.##...### +#########.#.. +#..#..##...## +.##..##.##### +#..#..#..##.. +#######.##.#. +####..#...... +#..##.#...##. +.##...#.#..## +.##...#.#..#. +#..##.#...##. + +###.#........ +..#.##....... +##.##..#..... +.##.##..##### +.#....#..#### +##...#..#.... +###..######## +.###..#..#..# +.#.#.#....... +######....... +#...#..###### +.##....###### +#...#.#.##### +.#.#...###### +####..#..#### + +###.... +###.... +.####.. +#.#.##. +..##..# +.##.#.# +#.####. +##.#.## +#.##.## +.#....# +.#.#.#. +.#..#.# +#..#### +#..#### +.#..#.# +.#.#.#. +.#.#..# + +####..##. +.##..#..# +....#.### +....#.##. +....#.#.. +.##..###. +.##..###. +....#.#.. +....#.##. +....#.### +.##..#..# +####..##. +##.###... +#..#...#. +####..... + +##....##### +.######.#.. +#..##..#... +#..##..#### +.######.... +.#......#.. +..#..#..### + +###.#...### +...####...# +..#..#..#.# +..##.#.#..# +###.##..### +###..#....# +##...#....# +###.##..### +..##.#.#..# +..#..#..#.# +...####...# +###.#...### +..####.#.#. + +...#.##..#...#... +#.#...###.##.#### +....#.#.##.#.##.. +.....#.#.####.#.. +.#.#.#.##..#.#### +.#.#...##..#.#### +.....#.#.####.#.. +....#.#.##.#.##.. +#.#...###.##.#### +...#.##..#...#... +...#....###...#.. +#..###.......##.. +.#.###.#.###.#### + +...####.. +.##....## +.######## +##......# +#..#..#.. +....##... +#..####.. + +####..##.## +###.#...##. +....#..#### +#...##..#.. +..#..#...#. +..#..#...#. +#...##..#.. +....#..#### +###.#...##. +####..##.## +..###...##. +#.#.#.##.#. +.####..#... +..###..#... +#.#.#.##.#. + +.....####.....#.. +##.#.#..#.#.##... +.#.#......#.#.### +...###..###...#.. +.#..######..#.#.. +####.####.#####.. +...###..###...#.. +#............#.## +..#.#.##.#.#.#... +#..###..###..#... +...#......#....## +##...####...##.## +#...##..##...#.## + +.####..###. +.##.###.#.. +.##.###.#.. +.####..###. +#.#.#.#.### +####.####.. +#.....##.#. +#.....##.#. +####.####.. +#.#.###.### +.####..###. + +.....#..#.. +#..###..### +####......# +.##.#.##.#. +#..#######. +#..#..##..# +.....#..#.. + +##..#.... +...#.#.## +###...### +....###.. +##..###.. +###.###.. +###....## +#....#... +####...## +##.###... +.......## +..#.###.. +##..###.. +...#..### +###...### + +..#.##.#...#### +##.#..#.##.#### +.###..###...... +.##....##...#.. +..##..##...#### +..#....#.....## +#.#..#.#.#..#.. +..#.##.#...#... +#...##...##..## +.##....##.##### +#...##...#..### +.#..##..#.###.. +#...##...##..## + +#....#.#. +###..###. +###..###. +#....#.#. +#.#.#..#. +...##..#. +.#..###.# +#...#.... +#...##... +##.###..# +#..##.##. +#..##.##. +##.###..# +#....#... +#...#.... +.#..###.# +...##..#. + +.#...#.#. +#.##.##.. +####..#.. +.#.###### +...##.### +...##.### +.#.#####. +####..#.. +#.##.##.. +.#...#.#. +.#...#.#. + +####.#..#.#####.# +##.##....##.####. +#..#.####.#..##.. +#####....######## +###..####..###### +#####....######## +#.##..##..##.##.# +##.#..##..#.####. +#..#......#..##.. +..##......##....# +#............##.. +##.##....##.####. +...#......#...... +....#.##.#....... +.####....####..## +.#..........#..#. +.##.#.##.#.##..## + +#..#...##.. +..######.## +..######.## +#..#..###.. +....#.#.... +##....##... +#.#.#.##..# +#.#.#.##..# +##....##... +....#.#.... +#..#..###.. + +#..#..#..#... +..##..##..##. +..#.##.#..#.# +############. +#.######.##.. +#.######.#.## +#.######.#..# +#.######.##.. +############. + +..##..###.#..#. +...#......#..#. +#.##.......##.. +.....##.#.#..#. +.....##.#.#..#. +#.##.......##.. +...#......#..#. +..##..###.#..#. +#.#.##...##..## +#####.##..#..#. +#......##...... +#.#..##.###...# +##.#......#..#. +##..#.#...#..#. +.#.###...###### + +##..#.#..##..###. +.##.#.#.#..##..#. +...#...##.#..#.## +.##.##...##..##.. +.##.##...##..##.. +...#...##.#..#.## +.##.#.#.#..##..#. + +.#.####..####.#.. +#.###.####.###.## +####..#..#..##### +..#.##.##.##.#... +#.##.#.##.#..#.## +#..#..####..#..## +#.####.##.####.## +##.###....###.### +##.#.#....#.#.### +..##...##...##... +..###..##..###... + +..#.#...##....#.. +####..#..#..###.# +#####.#..#..###.# +..#.#...##....#.. +##.#.##.....###.. +..####.########.. +...##.##.#####.#. +..#.#......#....# +##..####.#....... +..##...#...#.##.# +....#.##....#..## + +.#.##.##..# +####.#..##. +##..##.#### +##..##.#### +####.#..##. +...##.##..# +.#......... + +##.#..#.# +#.#.#..## +#####.##. +##..##... +##..##... +#####..#. +#.#.#..## +##.#..#.# +.##..##.. +.##..##.. +##.#..#.# + +###...##....#.### +#.#..#.#.#.###..# +.##.#.#.#.##.#.#. +.##.#.#.#.##.#.#. +#.#..#.#.#.###.## +###...##....#.### +...#.#.#.##..##.# +#....####..##.#.. +#....####..##.#.. +...#.#.#.##..##.# +###...##....#.### + +..#####.. +.###..... +#..###... +####.#... +###..#... +#..###... +.###..... +..#####.. +#.#.##### +..#.##### +##.#.#### + +...#....#####.. +..###..#...#.## +##..#.###.#.... +##....##.###... +..#..#...#..... +#..#.##.##.##.. +.#.#..##.#.#.## +##..###.....#.. +.##.##...##.#.. +##...##..##.### +##.#.##..##.### + +...####..##.##. +...#..#####.... +##..####.###..# +##..#####...##. +...#..#.#.#.... +..#..#.#....... +....#....#..##. +..####.#.#.#### +####.#....##... +####.#.#....... +####.####.##..# +..###.....#.... +##..###.###.##. + +.####.###.#.. +.####.###.#.. +########.###. +#.###.##....# +#...#...#.... +....##.#.#..# +.##......#### +#...##.....#. +#.##...##..## +####...##.##. +####...##.##. +#.##...##..## +##..##.....#. + +#......#.#### +.######.#...# +.........#### +##....##..#.. +.#.##.#..#..# +###..###...#. +..####..#.#.. +###..###..##. +........#.... +##....###...# +##....###...# +........#.#.. +###..###..##. +..####..#.#.. +###..###...#. + +.##.#.#...#...# +.##.#.#...#.#.# +#.##.####..###. +....#.#.##.#### +#..#.#.#.#..### +.##...##.##..## +..##.##...##.#. +..#.#..###.##.# +#####.##....#.# +#...#.#...##.## +#.###......#..# +##..#..###.#.## +..#####..#..### +..#####..#..### +##..#..###.#.## + +.##.##. +.#.##.# +#....#. +#....#. +.#.##.# +.##.##. +...#### +##....# +#.#.### +.####.# +###..#. +###.... +.####.# +#.#.### +##....# +...#### +.##.##. + +####.#....####..# +####.#....####..# +#..##...##.#..#.# +#..#..######..### +#..#..#.######### +.##..#.#...#.#... +#..###......#.##. +####.#.###...##.# +####.####..#..##. +....##.#.#....... +.##..##..#..#..## +###.#.#..#...#### +####.###.###.#.#. + +.###### +.###..# +.###..# +.###### +#..#..# +.#..### +.##..#. +.###... +##.#.#. +.##.... +..#..## +.....## +.##.... +##.#.#. +.###... + +##....#####...... +##....##.#..####. +.#....#..##.#..#. +##....##.#.##..## +.#.##.#....#....# +##....######.##.# +###..###.######.# +##....#####.####. +#......##..#....# +#.#..#.#..#.#..#. +.#.##.#...##.##.# +..####..#..#.##.# +.#.##.#.#..#....# + +.#.#..###.### +.#.#...##.### +##......####. +#...#.##.#... +##..#.###..#. +.####..#.###. +#...#..#..#.. +.####.##..#.. +.##..#..#...# +.##..#..#...# +.####.##..#.. +#...#..#..#.. +.####..#.###. + +#...#....#.#. +##.#.#.#.##.# +###.##...#.#. +###.##...#.#. +##.#.#.####.# +#...#....#.#. +..#.######..# +#...#..####.. +###..##.##.#. +...#.#.#..#.. +...#.#.#..#.. +###..##.##.#. +#...#..####.. + +..#.### +######. +..####. +###...# +###...# +..##.#. +######. +..#.### +..##.## +.....#. +###..## +..####. +######. +##...#. +####... +..#.#.. +##.###. + +.#..#.###.##...## +..##...#.##....#. +###########....#. +#######...###...# +#....##.#..#....# +#....#.##.#..##.# +.####.#.#.#.....# +.####....##.##..# +##..##..#..####.. +.#..#.#...####..# +#.##.##.#.###..#. +#.##.##.#.#.#..#. +.#..#.#...####..# +##..##..#..####.. +.####....##.##..# + +##..##.## +.#..#.... +..##..### +#.##.##.. +.......## +..##..... +#....##.. +..##...## +#....#.## +#.##.#.## +..##..... +#.##.#... +...#..### + +#..##....##..##.# +.###.####.###.### +###..#..#..#####. +.#.##.##.##.#...# +.#.##.##.##.#...# +###..#..#..#####. +.###.####.###.### +#..##....##..##.# +.#.##.##.##.#.#.. +....##..##.....## +#....#..#.#..#### +.#...####...#.#.# +#.#.#....#.#.##.# +#..##.##.##..#... +#....#..#....##.. + +#....#### +###...... +###...... +##...#### +....#.... +.#.#..##. +..###.... +##.#..... +...#..##. +#.###.##. +#....#### + +#..####..#.##.#.. +.########..##..## +#........#.##.#.. +###.##.###.##.### +###.##.####..#### +..##..##........# +..######........# +#.#.##.#.#.##.#.# +.##.##.##.####.## +#.##..##.##..#..# +.#.####.#......#. +....##....####... +.##.##.##......## + +..####..##..##..# +...#..##.####.##. +.##.#.##..##..##. +...#..##.####.##. +.##..#..#....#..# +##.##.##########. +#########.##.#### + +.###..###.#.#.### +###....###..##.#. +###.##.###.#.#.## +###.##.###.#.#.## +###....###..##.#. +.###..###.#.#.### +.#.####.#...#.#.. +##.#..#.###...#.. +####..###..#.###. +#..####..##.#..#. +#.######.##..#.## +.##.##.##.##..##. +####..######.#### +....##.....#.##.. +####..#####...### + +#...#.#.#...# +#.####.#..#.. +#.####.#..#.. +#...#.#.#...# +#.#.##...#.## +#####.#.#..#. +#.#....####.# +##.#.#.#####. +#####.##.#..# +....##.#...#. +.#..#...#.#.. +#.#.###...##. +...#..##...#. +..##..##...#. +#.#.###...##. +.#..#...#.#.. +....##.#...#. diff --git a/src/day13.rs b/src/day13.rs new file mode 100644 index 0000000..8e8f980 --- /dev/null +++ b/src/day13.rs @@ -0,0 +1,318 @@ +use core::panic; +use std::vec; + +#[derive(Debug)] +struct Pattern { + // The pattern is a 2D array of characters, where each character is either a '#' or a '.'. + pattern: Vec>, + + // Count of # in each column + columns: Vec, + // Count of # in each row + rows: Vec, +} + +impl Pattern { + fn find_mirror_column(&self, print: bool) -> impl Iterator { + let mut result = vec![]; + let mut last = None; + for (i, c) in self.columns.iter().enumerate() { + if print { + println!("find_mirror_column: i = {}, c = {}, last = {:?}", i, c, last); + } + if let Some(l) = last { + if l == *c { + if print { + println!("find_mirror_column: found potential mirror line at i = {}", i); + } + // Found a potential mirror line + // Iterate outwards from here + let mut found = true; + for d in 1.. { + let check_column = i + d; + let other_column: isize = (i as isize) - (d as isize) - 1; + if check_column >= self.columns.len() || other_column < 0 { + if print { + println!("find_mirror_column: hit boundary, i = {}, d = {}, check_column = {}, other_column = {}", i, d, check_column, other_column); + } + break; + } + // Cheap compare first: If the numbers don't match, don't bother. + if self.columns[check_column] != self.columns[other_column as usize] { + if print { + println!("find_mirror_column: not matching numbers, i = {}, d = {}, [{}] = {} <> [{}] = {}", i, d, check_column, self.columns[check_column], other_column, self.columns[other_column as usize]); + } + found = false; + break; + } + // Ok, need the patterns. + for row in 0..self.pattern.len() { + if self.pattern[row][check_column] != self.pattern[row][other_column as usize] { + if print { + println!("find_mirror_column: not matching pattern, i = {}, d = {}, row = {}", i, d, row); + } + found = false; + break; + } + } + + // Proceed with the next pair. + } + + if found { + result.push(i); + } + } + } + last = Some(*c); + } + + result.into_iter() + } + + fn find_mirror_row(&self, print: bool) -> impl Iterator { + let mut result = vec![]; + let mut last = None; + for (i, c) in self.rows.iter().enumerate() { + if print { + println!("find_mirror_row: i = {}, c = {}, last = {:?}", i, c, last); + } + if let Some(l) = last { + if l == *c { + if print { + println!("find_mirror_row: found potential mirror line at i = {}", i); + } + // Found a potential mirror line + // Iterate outwards from here + let mut found = true; + for d in 1.. { + let check_row = i + d; + let other_row: isize = (i as isize) - (d as isize) - 1; + if check_row >= self.pattern.len() || other_row < 0 { + if print { + println!("find_mirror_row: hit boundary, i = {}, d = {}, check_row = {}, other_row = {}", i, d, check_row, other_row); + } + break; + } + // Cheap compare first: If the numbers don't match, don't bother. + if self.rows[check_row] != self.rows[other_row as usize] { + if print { + println!("find_mirror_row: not matching numbers, i = {}, d = {}, [{}] = {} <> [{}] = {}", i, d, check_row, self.rows[check_row], other_row, self.rows[other_row as usize]); + } + found = false; + break; + } + // Ok, need the patterns. + for row in 0..self.pattern.len() { + if self.pattern[check_row] != self.pattern[other_row as usize] { + if print { + println!("find_mirror_row: not matching pattern, i = {}, d = {}, row = {}", i, d, row); + } + found = false; + break; + } + } + + // Proceed with the next pair. + } + + if found { + result.push(i); + } + } + } + last = Some(*c); + } + + result.into_iter() + } + + pub fn find_mirror(&self, print: bool) -> impl Iterator, Option)> { + // Search until we find the same column twice: If it is a mirror line, then we can extend from there + // and compare the columns. If both comparison directions hit the border, the line is a mirror, otherwise + // proceed. + self.find_mirror_column(print).map(|column| (Some(column), None)).into_iter().chain( + self.find_mirror_row(print).map(|row| (None, Some(row))).into_iter() + ) + } +} + +impl std::str::FromStr for Pattern { + type Err = (); + + fn from_str(s: &str) -> Result { + let mut columns = vec![]; + let mut rows = vec![]; + let pattern = s.lines().map(|line| { + let row: Vec<_> = line.chars().collect(); + let mut row_count = 0; + for (i, c) in row.iter().enumerate() { + if i >= columns.len() { + columns.push(0); + } + if *c == '#' { + columns[i] += 1; + row_count += 1; + } + } + rows.push(row_count); + row + }).collect(); + Ok(Pattern { + pattern, + columns, + rows, + }) + } +} + +fn print_pattern(pattern: &Pattern, prefix: impl Fn(usize) -> String, suffix: impl Fn(usize) -> String) { + for (r, row) in pattern.pattern.iter().enumerate() { + print!("{}", prefix(r)); + for c in row.iter() { + print!("{}", c); + } + println!("{}", suffix(r)); + } +} + +fn print_pattern_with_column_indicator(pattern: &Pattern, column: usize) { + let row_len = pattern.pattern[0].len(); + let mut header = String::from(""); + for i in 0..row_len { + header.push((((i + 1) % 10) as u8 + b'0') as char); + } + let mut indicator = String::from(""); + for i in 0..row_len { + if i == column - 1 { + indicator.push('>'); + } else if i == column { + indicator.push('<'); + } else { + indicator.push(' '); + } + } + + println!("{}", header); + println!("{}", indicator); + print_pattern(pattern, |_| String::from(""), |_| String::from("")); + println!("{}", indicator); + println!("{}", header); +} + +fn print_pattern_with_row_indicator(pattern: &Pattern, row: usize) { + print_pattern(pattern, |r| { + let mut prefix = String::from((((r + 1) % 10) as u8 + b'0') as char); + if r == row - 1 { + prefix.push('v'); + } else if r == row { + prefix.push('^'); + } else { + prefix.push(' '); + } + prefix + }, |r| { + let mut prefix = String::from(""); + if r == row - 1 { + prefix.push('v'); + } else if r == row { + prefix.push('^'); + } else { + prefix.push(' '); + } + prefix.push((((r + 1) % 10) as u8 + b'0') as char); + prefix + }) +} + +fn print_pattern_and_mirror_indicators(pattern: &Pattern, column: Option, row: Option) { + if let Some(column) = column { + print_pattern_with_column_indicator(pattern, column); + } else if let Some(row) = row { + print_pattern_with_row_indicator(pattern, row); + } else { + print_pattern(pattern, |_| String::from(""), |_| String::from("")); + } +} + +pub fn main() { + match std::fs::read_to_string("day13.input") { + Ok(mut input) => { + let mut result = 0; + let mut tmp = String::from(""); + // Make sure we can find an empty line at the end: + input.push('\n'); + for (i, line) in input.split('\n').enumerate() { + if line.is_empty() { + // Ignore multiple consecutive empty lines + if tmp.is_empty() { + continue; + } + let pattern = tmp.parse::().unwrap(); + let mut num_mirror_lines = 0; + for (c, r) in pattern.find_mirror(false) { + if num_mirror_lines == 0 { + print_pattern_and_mirror_indicators(&pattern, c, r); + } + if let Some(columns_before) = c { + println!("columns_before = {}", columns_before); + num_mirror_lines += 1; + result += columns_before; + } else if let Some(rows_before) = r { + println!("rows_before = {}", rows_before); + num_mirror_lines += 1; + result += 100 * rows_before; + } else { + panic!("no mirror found, line = {}, pattern = {:?}", i, pattern); + } + if num_mirror_lines == 1 { + break; + } + } + println!(); + tmp.clear(); + } else { + tmp.push_str(line); + tmp.push('\n'); + } + } + println!("summarized = {}", result); + } + Err(reason) => println!("error = {}", reason), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + static DATA1: &str = "#.##..##. +..#.##.#. +##......# +##......# +..#.##.#. +..##..##. +#.#.##.#."; + + static DATA2: &str = "#...##..# +#....#..# +..##..### +#####.##. +#####.##. +..##..### +#....#..#"; + + #[test] + fn example1_data1() { + let pattern = DATA1.parse::().unwrap(); + assert_eq!(pattern.find_mirror(true).collect::>(), vec![(Some(5), None)]); + print_pattern_with_column_indicator(&pattern, 5) + } + + #[test] + fn example1_data2() { + let pattern = DATA2.parse::().unwrap(); + assert_eq!(pattern.find_mirror(true).collect::>(), vec![(None, Some(4))]); + print_pattern_with_row_indicator(&pattern, 4) + } +} diff --git a/src/main.rs b/src/main.rs index 04376eb..430b603 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day12; +mod day13; fn main() { - day12::main() + day13::main() } From b60ebdcc92c68ee7af7ea009c00af9f435ca05c8 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Mon, 18 Dec 2023 22:21:36 +0100 Subject: [PATCH 107/120] Day 13, part 1: Actually verify before making assumptions --- src/day13.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/src/day13.rs b/src/day13.rs index 8e8f980..cd6e4e7 100644 --- a/src/day13.rs +++ b/src/day13.rs @@ -16,7 +16,7 @@ impl Pattern { fn find_mirror_column(&self, print: bool) -> impl Iterator { let mut result = vec![]; let mut last = None; - for (i, c) in self.columns.iter().enumerate() { + 'outer: for (i, c) in self.columns.iter().enumerate() { if print { println!("find_mirror_column: i = {}, c = {}, last = {:?}", i, c, last); } @@ -25,6 +25,17 @@ impl Pattern { if print { println!("find_mirror_column: found potential mirror line at i = {}", i); } + + // Verify: The patterns must be the same now between this column and the previous column. + for row in 0..self.pattern.len() { + if self.pattern[row][i] != self.pattern[row][i - 1] { + if print { + println!("find_mirror_column: not matching pattern, i = {}, row = {}", i, row); + } + continue 'outer; + } + } + // Found a potential mirror line // Iterate outwards from here let mut found = true; @@ -73,15 +84,23 @@ impl Pattern { fn find_mirror_row(&self, print: bool) -> impl Iterator { let mut result = vec![]; let mut last = None; - for (i, c) in self.rows.iter().enumerate() { + 'outer: for (i, c) in self.rows.iter().enumerate() { if print { - println!("find_mirror_row: i = {}, c = {}, last = {:?}", i, c, last); + println!("find_mirror_row: row = \"{}\", i = {}, c = {}, last = {:?}", self.pattern[i].iter().collect::(), i, c, last); } if let Some(l) = last { if l == *c { if print { println!("find_mirror_row: found potential mirror line at i = {}", i); } + // Verify: The patterns must be the same now between this row and the previous row. + if self.pattern[i] != self.pattern[i - 1] { + if print { + println!("find_mirror_row: not matching pattern, i = {}", i); + } + continue 'outer; + } + // Found a potential mirror line // Iterate outwards from here let mut found = true; @@ -131,9 +150,12 @@ impl Pattern { // Search until we find the same column twice: If it is a mirror line, then we can extend from there // and compare the columns. If both comparison directions hit the border, the line is a mirror, otherwise // proceed. - self.find_mirror_column(print).map(|column| (Some(column), None)).into_iter().chain( - self.find_mirror_row(print).map(|row| (None, Some(row))).into_iter() + self.find_mirror_row(print).map(|row| (None, Some(row))).chain( + self.find_mirror_column(print).map(|column| (Some(column), None)) ) + // self.find_mirror_column(print).map(|column| (Some(column), None)).chain( + // self.find_mirror_row(print).map(|row| (None, Some(row))) + // ) } } @@ -315,4 +337,40 @@ mod tests { assert_eq!(pattern.find_mirror(true).collect::>(), vec![(None, Some(4))]); print_pattern_with_row_indicator(&pattern, 4) } + + #[test] + fn example1_test1() { + const INPUT: &str = "##...##.. +.##.#..#. +.#....... +...#.##.# +##..#..#. +.##..##.. +.#...##.. +#.####### +....####. +..##.##.# +..##.##.# +....####. +#.####### +.#...##.. +.##..##.. +#...#..#. +...#.##.#"; + let pattern = INPUT.parse::().unwrap(); + assert_eq!(pattern.find_mirror(true).collect::>(), vec![(Some(6), None)]); + } + + #[test] + fn example1_test2() { + const INPUT: &str = "....#....##.... +.##..##.####.## +#..#.#...##...# +.##.####....### +#..#.##.####.## +#..###.#.##.#.# +.##.##.##..####"; + let pattern = INPUT.parse::().unwrap(); + assert_eq!(pattern.find_mirror(true).collect::>(), vec![(Some(2), None)]); + } } From d7c21ba8ce5495d0e3dacc8dff67a258195f2918 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 13:28:01 +0100 Subject: [PATCH 108/120] SWitch to using bitstrings for matching and allow for a specified amount of errors --- src/day13.rs | 138 +++++++++++++++++++++++---------------------------- 1 file changed, 61 insertions(+), 77 deletions(-) diff --git a/src/day13.rs b/src/day13.rs index cd6e4e7..dc305cf 100644 --- a/src/day13.rs +++ b/src/day13.rs @@ -6,36 +6,31 @@ struct Pattern { // The pattern is a 2D array of characters, where each character is either a '#' or a '.'. pattern: Vec>, - // Count of # in each column - columns: Vec, - // Count of # in each row - rows: Vec, + // Bit pattern per column, # is 1. + // The MSB represents the top row, the LSB the bottom row (possibly filled up with 0). + columns: Vec, + // Bit pattern per row, # is 1. + // The MSB represents the left column, the LSB the right column (possibly filled up with 0). + rows: Vec, } impl Pattern { - fn find_mirror_column(&self, print: bool) -> impl Iterator { + fn find_mirror_column(&self, max_errors: u32, print: bool) -> impl Iterator { let mut result = vec![]; let mut last = None; - 'outer: for (i, c) in self.columns.iter().enumerate() { + for (i, c) in self.columns.iter().enumerate() { if print { - println!("find_mirror_column: i = {}, c = {}, last = {:?}", i, c, last); + println!("find_mirror_column: i = {}, c = {:032b}, last = {:032b}", i, c, last.unwrap_or(0)); } if let Some(l) = last { - if l == *c { + // Calculate the number of errors between this and the previous row. If we still have some + // left from our budget, proceed checking further. + let mut errors_left = (max_errors as i32) - (((l as u32) ^ *c).count_ones() as i32); + if errors_left >= 0 { if print { println!("find_mirror_column: found potential mirror line at i = {}", i); } - // Verify: The patterns must be the same now between this column and the previous column. - for row in 0..self.pattern.len() { - if self.pattern[row][i] != self.pattern[row][i - 1] { - if print { - println!("find_mirror_column: not matching pattern, i = {}, row = {}", i, row); - } - continue 'outer; - } - } - // Found a potential mirror line // Iterate outwards from here let mut found = true; @@ -48,24 +43,16 @@ impl Pattern { } break; } - // Cheap compare first: If the numbers don't match, don't bother. - if self.columns[check_column] != self.columns[other_column as usize] { + // Count errors between these rows. + let errors = (self.columns[check_column] ^ self.columns[other_column as usize]).count_ones() as i32; + errors_left -= errors; + if errors_left < 0 { if print { - println!("find_mirror_column: not matching numbers, i = {}, d = {}, [{}] = {} <> [{}] = {}", i, d, check_column, self.columns[check_column], other_column, self.columns[other_column as usize]); + println!("find_mirror_column: not matching, i = {}, d = {}, [{}] = {:032b} <> [{}] = {:032b}", i, d, check_column, self.columns[check_column], other_column, self.columns[other_column as usize]); } found = false; break; } - // Ok, need the patterns. - for row in 0..self.pattern.len() { - if self.pattern[row][check_column] != self.pattern[row][other_column as usize] { - if print { - println!("find_mirror_column: not matching pattern, i = {}, d = {}, row = {}", i, d, row); - } - found = false; - break; - } - } // Proceed with the next pair. } @@ -81,28 +68,24 @@ impl Pattern { result.into_iter() } - fn find_mirror_row(&self, print: bool) -> impl Iterator { + fn find_mirror_row(&self, max_errors: u32, print: bool) -> impl Iterator { let mut result = vec![]; let mut last = None; - 'outer: for (i, c) in self.rows.iter().enumerate() { + for (i, c) in self.rows.iter().enumerate() { if print { - println!("find_mirror_row: row = \"{}\", i = {}, c = {}, last = {:?}", self.pattern[i].iter().collect::(), i, c, last); + println!("find_mirror_row: row = \"{}\", i = {}, c = {:032b}, last = {:032b}", self.pattern[i].iter().collect::(), i, c, last.unwrap_or(0)); } if let Some(l) = last { - if l == *c { + // Calculate the number of errors between this and the previous row. If we still have some + // left from our budget, proceed checking further. + let mut errors_left = (max_errors as i32) - (((l as u32) ^ *c).count_ones() as i32); + if errors_left >= 0 { + // Found a potential mirror line + // Iterate outwards from here if print { println!("find_mirror_row: found potential mirror line at i = {}", i); } - // Verify: The patterns must be the same now between this row and the previous row. - if self.pattern[i] != self.pattern[i - 1] { - if print { - println!("find_mirror_row: not matching pattern, i = {}", i); - } - continue 'outer; - } - // Found a potential mirror line - // Iterate outwards from here let mut found = true; for d in 1.. { let check_row = i + d; @@ -113,24 +96,16 @@ impl Pattern { } break; } - // Cheap compare first: If the numbers don't match, don't bother. - if self.rows[check_row] != self.rows[other_row as usize] { + // Count errors between these rows. + let errors = (self.rows[check_row] ^ self.rows[other_row as usize]).count_ones() as i32; + errors_left -= errors; + if errors_left < 0 { if print { - println!("find_mirror_row: not matching numbers, i = {}, d = {}, [{}] = {} <> [{}] = {}", i, d, check_row, self.rows[check_row], other_row, self.rows[other_row as usize]); + println!("find_mirror_row: not matching, i = {}, d = {}, [{}] = {:032b} <> [{}] = {:032b}", i, d, check_row, self.rows[check_row], other_row, self.rows[other_row as usize]); } found = false; break; } - // Ok, need the patterns. - for row in 0..self.pattern.len() { - if self.pattern[check_row] != self.pattern[other_row as usize] { - if print { - println!("find_mirror_row: not matching pattern, i = {}, d = {}, row = {}", i, d, row); - } - found = false; - break; - } - } // Proceed with the next pair. } @@ -146,15 +121,17 @@ impl Pattern { result.into_iter() } - pub fn find_mirror(&self, print: bool) -> impl Iterator, Option)> { + pub fn find_mirror(&self, max_errors: u32, print: bool) -> impl Iterator, Option)> { // Search until we find the same column twice: If it is a mirror line, then we can extend from there // and compare the columns. If both comparison directions hit the border, the line is a mirror, otherwise // proceed. - self.find_mirror_row(print).map(|row| (None, Some(row))).chain( - self.find_mirror_column(print).map(|column| (Some(column), None)) + // NB: The task doesn't specify whether horizontal or vertical is "more important", so in theory both + // configurations should give the same results ... + self.find_mirror_row(max_errors, print).map(|row| (None, Some(row))).chain( + self.find_mirror_column(max_errors, print).map(|column| (Some(column), None)) ) - // self.find_mirror_column(print).map(|column| (Some(column), None)).chain( - // self.find_mirror_row(print).map(|row| (None, Some(row))) + // self.find_mirror_column(max_errors, print).map(|column| (Some(column), None)).chain( + // self.find_mirror_row(max_errors, print).map(|row| (None, Some(row))) // ) } } @@ -165,20 +142,27 @@ impl std::str::FromStr for Pattern { fn from_str(s: &str) -> Result { let mut columns = vec![]; let mut rows = vec![]; - let pattern = s.lines().map(|line| { - let row: Vec<_> = line.chars().collect(); - let mut row_count = 0; - for (i, c) in row.iter().enumerate() { - if i >= columns.len() { + let pattern = s.lines().enumerate().map(|(r, line)| { + let pattern_row: Vec<_> = line.chars().collect(); + let mut row = 0; + for (c, ch) in pattern_row.iter().enumerate() { + if c >= columns.len() { columns.push(0); } - if *c == '#' { - columns[i] += 1; - row_count += 1; + + // Note that we don't know the width or height here, but to get the bits + // into a natural order we can just align them on the word size instead: + // + // ##...##.. + // 123456789 + // 1 110001100 + if *ch == '#' { + columns[c] |= 1 << (31 - r); + row |= 1 << (31 - c); } } - rows.push(row_count); - row + rows.push(row); + pattern_row }).collect(); Ok(Pattern { pattern, @@ -272,7 +256,7 @@ pub fn main() { } let pattern = tmp.parse::().unwrap(); let mut num_mirror_lines = 0; - for (c, r) in pattern.find_mirror(false) { + for (c, r) in pattern.find_mirror(0, false) { if num_mirror_lines == 0 { print_pattern_and_mirror_indicators(&pattern, c, r); } @@ -327,14 +311,14 @@ mod tests { #[test] fn example1_data1() { let pattern = DATA1.parse::().unwrap(); - assert_eq!(pattern.find_mirror(true).collect::>(), vec![(Some(5), None)]); + assert_eq!(pattern.find_mirror(0, true).collect::>(), vec![(Some(5), None)]); print_pattern_with_column_indicator(&pattern, 5) } #[test] fn example1_data2() { let pattern = DATA2.parse::().unwrap(); - assert_eq!(pattern.find_mirror(true).collect::>(), vec![(None, Some(4))]); + assert_eq!(pattern.find_mirror(0, true).collect::>(), vec![(None, Some(4))]); print_pattern_with_row_indicator(&pattern, 4) } @@ -358,7 +342,7 @@ mod tests { #...#..#. ...#.##.#"; let pattern = INPUT.parse::().unwrap(); - assert_eq!(pattern.find_mirror(true).collect::>(), vec![(Some(6), None)]); + assert_eq!(pattern.find_mirror(0, true).collect::>(), vec![(Some(6), None)]); } #[test] @@ -371,6 +355,6 @@ mod tests { #..###.#.##.#.# .##.##.##..####"; let pattern = INPUT.parse::().unwrap(); - assert_eq!(pattern.find_mirror(true).collect::>(), vec![(Some(2), None)]); + assert_eq!(pattern.find_mirror(0, true).collect::>(), vec![(Some(2), None)]); } } From d48b455184ed55a0f2bb04bd2b63374f0ecd4473 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 13:36:40 +0100 Subject: [PATCH 109/120] Improve formatting and add tests Note that this will be removed in the next iteration: The task doesn't ask for "max errors", but rather for "exactly". --- src/day13.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/day13.rs b/src/day13.rs index dc305cf..538bd17 100644 --- a/src/day13.rs +++ b/src/day13.rs @@ -242,6 +242,9 @@ fn print_pattern_and_mirror_indicators(pattern: &Pattern, column: Option, } pub fn main() { + // Part 1: 0, Part 2: 1. + static MAX_ERRORS: u32 = 1; + match std::fs::read_to_string("day13.input") { Ok(mut input) => { let mut result = 0; @@ -256,7 +259,7 @@ pub fn main() { } let pattern = tmp.parse::().unwrap(); let mut num_mirror_lines = 0; - for (c, r) in pattern.find_mirror(0, false) { + for (c, r) in pattern.find_mirror(MAX_ERRORS, false) { if num_mirror_lines == 0 { print_pattern_and_mirror_indicators(&pattern, c, r); } @@ -282,7 +285,7 @@ pub fn main() { tmp.push('\n'); } } - println!("summarized = {}", result); + println!("summarized with MAX_ERRORS = {}: {}", MAX_ERRORS, result); } Err(reason) => println!("error = {}", reason), } @@ -354,7 +357,21 @@ mod tests { #..#.##.####.## #..###.#.##.#.# .##.##.##..####"; - let pattern = INPUT.parse::().unwrap(); - assert_eq!(pattern.find_mirror(0, true).collect::>(), vec![(Some(2), None)]); - } + let pattern = INPUT.parse::().unwrap(); + assert_eq!(pattern.find_mirror(0, true).collect::>(), vec![(Some(2), None)]); + } + + #[test] + fn example2_data1() { + let pattern = DATA1.parse::().unwrap(); + assert_eq!(pattern.find_mirror(1, true).collect::>(), vec![(None, Some(3)), (Some(5), None)]); + print_pattern_with_row_indicator(&pattern, 3) + } + + #[test] + fn example2_data2() { + let pattern = DATA2.parse::().unwrap(); + assert_eq!(pattern.find_mirror(1, true).collect::>(), vec![(None, Some(1)), (None, Some(4))]); + print_pattern_with_row_indicator(&pattern, 1) + } } From 5414e57a866e1d689c39b06fca9c32eb3c5f5574 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 13:40:17 +0100 Subject: [PATCH 110/120] Switch to "exactly" checking for errors --- src/day13.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/day13.rs b/src/day13.rs index 538bd17..fcab2b2 100644 --- a/src/day13.rs +++ b/src/day13.rs @@ -15,7 +15,7 @@ struct Pattern { } impl Pattern { - fn find_mirror_column(&self, max_errors: u32, print: bool) -> impl Iterator { + fn find_mirror_column(&self, errors: u32, print: bool) -> impl Iterator { let mut result = vec![]; let mut last = None; for (i, c) in self.columns.iter().enumerate() { @@ -25,7 +25,7 @@ impl Pattern { if let Some(l) = last { // Calculate the number of errors between this and the previous row. If we still have some // left from our budget, proceed checking further. - let mut errors_left = (max_errors as i32) - (((l as u32) ^ *c).count_ones() as i32); + let mut errors_left = (errors as i32) - (((l as u32) ^ *c).count_ones() as i32); if errors_left >= 0 { if print { println!("find_mirror_column: found potential mirror line at i = {}", i); @@ -57,7 +57,7 @@ impl Pattern { // Proceed with the next pair. } - if found { + if found && errors_left == 0 { result.push(i); } } @@ -68,7 +68,7 @@ impl Pattern { result.into_iter() } - fn find_mirror_row(&self, max_errors: u32, print: bool) -> impl Iterator { + fn find_mirror_row(&self, errors: u32, print: bool) -> impl Iterator { let mut result = vec![]; let mut last = None; for (i, c) in self.rows.iter().enumerate() { @@ -78,7 +78,7 @@ impl Pattern { if let Some(l) = last { // Calculate the number of errors between this and the previous row. If we still have some // left from our budget, proceed checking further. - let mut errors_left = (max_errors as i32) - (((l as u32) ^ *c).count_ones() as i32); + let mut errors_left = (errors as i32) - (((l as u32) ^ *c).count_ones() as i32); if errors_left >= 0 { // Found a potential mirror line // Iterate outwards from here @@ -110,7 +110,7 @@ impl Pattern { // Proceed with the next pair. } - if found { + if found && errors_left == 0 { result.push(i); } } @@ -243,7 +243,7 @@ fn print_pattern_and_mirror_indicators(pattern: &Pattern, column: Option, pub fn main() { // Part 1: 0, Part 2: 1. - static MAX_ERRORS: u32 = 1; + static ERRORS: u32 = 1; match std::fs::read_to_string("day13.input") { Ok(mut input) => { @@ -259,7 +259,7 @@ pub fn main() { } let pattern = tmp.parse::().unwrap(); let mut num_mirror_lines = 0; - for (c, r) in pattern.find_mirror(MAX_ERRORS, false) { + for (c, r) in pattern.find_mirror(ERRORS, false) { if num_mirror_lines == 0 { print_pattern_and_mirror_indicators(&pattern, c, r); } @@ -285,7 +285,7 @@ pub fn main() { tmp.push('\n'); } } - println!("summarized with MAX_ERRORS = {}: {}", MAX_ERRORS, result); + println!("summarized with {} errors: {}", ERRORS, result); } Err(reason) => println!("error = {}", reason), } @@ -364,14 +364,14 @@ mod tests { #[test] fn example2_data1() { let pattern = DATA1.parse::().unwrap(); - assert_eq!(pattern.find_mirror(1, true).collect::>(), vec![(None, Some(3)), (Some(5), None)]); + assert_eq!(pattern.find_mirror(1, true).collect::>(), vec![(None, Some(3))]); print_pattern_with_row_indicator(&pattern, 3) } #[test] fn example2_data2() { let pattern = DATA2.parse::().unwrap(); - assert_eq!(pattern.find_mirror(1, true).collect::>(), vec![(None, Some(1)), (None, Some(4))]); + assert_eq!(pattern.find_mirror(1, true).collect::>(), vec![(None, Some(1))]); print_pattern_with_row_indicator(&pattern, 1) } } From 6e5980ee023cc1c021e0f61b46c5c2d33ec5272a Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 19:22:28 +0100 Subject: [PATCH 111/120] Day 14, part 1: Suspiciously trivial --- day14.input | 100 ++++++++++++++++++++++++++++++++++++ src/day14.rs | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 +- 3 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 day14.input create mode 100644 src/day14.rs diff --git a/day14.input b/day14.input new file mode 100644 index 0000000..de05e47 --- /dev/null +++ b/day14.input @@ -0,0 +1,100 @@ +...###.#OO..#.O......#...#...O..#.....#...O#..O#........O.#O#O..O.....O.......#O.............O#.O### +O.OOO..##O....#O.O.OO#......O...#O.........O....O..OO....#OOO.#..#..........O.O...##...#........O..# +.#..O..O.#.....O...O.....#O.OOOO..O.#.O#OO.........O.#.O#O.O.#...O#..........OOO.#...#..O#..####O.OO +.#..O....#.#..O.....O..O......O......O.O.O.#..O..#.OO.O.OOO..O#.O.##...OO.#.#.O..#...####O..#..#O... +.##.O......#.OO.O.O...O.....##O.#.#.......##.O....O...O.O.####...#.....O#.O....#O.#..O......O....... +O.###.#.#.O.O........#O.#.#..O#.#.OO....#O....O..##.#O.#.O.###.#..#..#.#.O....#..O......OO.#OO#...O# +.....O..O#..O.O...O....#O#.O.#O...O##OO.O.#O....#.#.....#..O#...#..##....#.OOO..#O.....#..#O#OO.O... +#............O#O.#.#.....O.O..OO....#....#..OO#.#O.OOO..#O...O#.....#.O....O.O..#....O..#...#OO#.... +..#.#O#..OO.O...##..#......#OO.....#.#.#.....#.O.....O.......#.##.......#O..OOO...........O.....O.O. +......O#O......OO#..O.#O..O..#....O..O.........O...#.#.##.O....O..O..O..O#.O.O.OOOOO....O#.O.......# +O##...O#...#..#.O.....#.O.###.O......#..#..O.#.O..........O..#.O.......#O......#.O.##....#.#.#...#.. +#..#.O..#..........#.O.#.O....#O#...OOOO......#...#.O.....O.OO.O....#.......O.O....O.O#.#O.###O.OO.# +OO.O#.O.......#.OO##....#O.#.O...O..#O.OO.....O..O#..##.O#...O...O.#.#O..O..O#........OO#.....O#..## +......O....O...#O##....OOO..O.O..O.......OO#O....###..O..##...O#.#.O.O..O.OO##....O.O#..O.#.#O#.#... +..O....#.....O..O.OO#..#.##..........#OO...#..#.O...O.O#...#....O.O..O...O....OO...O..OO#O....O..#O. +O....OO............O#.#........#..O.O...#OOO#.............#...OO......O#......O..O....OO...O..O...O. +...O##O.#..........O.O..##....O.##....O...#......O.O...O..O.O..O.##.#..#..O.O#.O.##..O..OO...OO..... +#.O#.#....#....O..O.O.O.###..O.O......O...OO#..........OO.....#O..#........#..#..O.#...##OO.#O#.#.#. +.##OO#...#O....O.O.#.#O....O.#...OO.....O...O.#.....O.OO.O..OO.....O...#..#.....#..#.....#..OOO..O## +.O#.........O.#..O.O.....O#.O##.##......OO.O.#......#...O##.O..#.....O...................#...O..O.#. +..###...#O...O#..#......OO#...##.#.O....#.##OO.....O..O......O#.O....O.#..O#.O#O.#.#O..##.O...O..O.# +.........#O...#..O.##.OO.....#...#.....O.O.O....O..##.O.....##OOO..#..O.#....#.##..O..##.O..#...#.#O +.O..#.#.O#..#OOOO#...#.O..#O#....OO....O..O..#...O..#...#........#O.O...#....O.#...#..#....O..OOOO.O +....#.#O#.O.O.O.OO.#....OO.....O.#....#...#..........#.##...##.OO#..OO.....O.....O#..O.#.....OO..#.. +.....OOOOO...O.........#.#....#..OO##.##.....#O....O..##..O.......#.....#.O.....#..O..OO.........O.. +...#.#.O###..#...O....OO....O.#.O.....##OO.O#..#.##....O.....OO##...O#OO..O.OO...O.OO..O#..O#.O..#.# +..OOO.OO...##O.O.O#.O...O..O#..OOO...##.#..#.#.#...O.#O#...O#O.OOO.O.OO.O..#.OOOO#.........#..OO...O +O...O#.O.OO#.OO.##.....#....#...#.........###.O.#.........O......#OO..O...OO.#O..#..#..O..O..##....# +O.OOO#....O..O#O....O...O.#......##O...OO..O.............#.#....O#..#O.#OO.O...OO...OOO...O.O.....O. +..#..O.OOO.....O#....#.#..O.......O...#.......#.OO..O.....#.#.#..O....#.#...O.O....O.#.......#.O##.. +.#..O.....#.#..#.#.#..OO.O...O........OO#.O..O..#..O#.##O..#....#....OO.....#..#O.........#.O..O.O.O +...O.##OO.#.......O...O.O.#.O.O..#.O...O.O..OO..O..#..OO..##....##.#.....#.O.#..........O.#.OOO#O... +...O..O....##...#...O#.O....O.O...#OO..O.#OO#........#O...OO.#..OO.#O.O..#....O#.O....O#......O#...# +..OO#O.O...#..#.#.......O.O...##....O..#.##..#...#...O...#.O#O.O....O......#....#...O..##..#O..O.... +.O...##O.#O.....O........O...O#....##......##....O.....##.....##......O....O..#..#O.#.O.OO#O#O....## +.........#O.O.O.OO..#.O#.##.....#.#O.O..O#.O........O....#O#.##O.#.O....#..OO.O.#...OO.#.O.##O...O## +..O##O.O......#O.O.#..O.#.........O...#..#..#..##OO....O..OO.#.#...OO...#O..#...O.###...O#.#......O. +......O..#O....O##...O##..........O...O....O........O..#OOO...OO..#.....##O.#.O..#....OO....O...#O.. +O..#.O..#.O..OOO..O.O.#.O...#O..#.O..#O......O.OO..O.#..O..##.....##....O#OOO..#.#O...O##...OO.#O#.O +O##.O...O.O.....O.#O..O..#.....#O.#.....###..OOO.OO#...#.O..O...........O.....O..#...O.#...#..O....O +...O.OO.....#O..O..#O..#O....OO....O....#O..#OO...O.#...O..#....#....#..OO.O.##.O#O...O.#O...O#..... +.....#...OO.........##OO.#.#........#..O..O.#.#.OO.#..#..#....#.O#..........#..O.O...O.#OO.....##... +#...#.....OO.....OOOO...#..#O.#..##.#..#..O.O##.O#.O#.O.O...#........#...O#......O.O#O..#..#..O...#. +.....O..#.OO.#O.O...#...#..#.......O#.##..OOOO.........OO.O.#O#...OO.#...O....###O..OO#.O.....#.##.O +#O..O#O.#..O#.O.O.O...O...OO...#.##....O#.......OO.O...#.....###.......O..#.O..O...OO#.O.#O.O.O.O.O. +OO.....O.............#.O...OO..##O.O#.#O.#....O..........O..O#.........#.........O#.#....#O#..#..##O +#..#..#........O.OO....O.....O..#O..O#.#O#O...#.##O..O...O.#O.#OOOO#.OO.#..OO##..#O.#.O.O...O..O#... +...#........O...O.O..O.O#.....#....O.#.#OO.#...#..O#O.##..#.##...O#.#.....O..O.....#..O#.....O...... +..O.O.O###..#..O.#..#........O..O#..##O#....#...#.....O.......OO...O....##......#.O..O..O.O.O.O..#O. +..O..O..OOO.O##..O..O#..OO###.#....O..O...##..OOO...O.......#..#..OO..O...OO#.O.....O.O..O.OO.#....O +O....O...#.O#O#....#.O....##...O.........O...#.#.#O.OO..O#....O.##.....#.#..#..#....#.#O..O.O.#..O.. +O................O#O.O......##..#O...O....O#.O..#....O......O.#..O....O.#...O.....O##.#.O....OOO.#.# +...O#....#..O.O........O#.O#.#O.#.....#....O#....#..#......O.....#.....O#O..O..OO.#.#OOO#O.O.O#..... +.#.#O..##.O.O.O#...O...#...#....O..OO..O..#..#....###.O#.OO.O....O....OOO...O....OOO#..#..O.....#.OO +...OOO..O.O.....O#.##O#.#.#.O..#O.....#O....O#O...O....O#.O#..O#.O..#.#.#O..O..O.#....O.....#O.....# +.O#...#...O.....O..#.O.#.....O...O#..#.....O.O#O..O.....#.#.O..O..#.OO..#O...O......#OOO..#.O..O..#. +O.#.OO.#.O#O#...O....#...###OO..OOO.#O..O.O..O........##...O#...#...O##OO.O#....O.#O.O..O#.O..O.#..O +...#...O.O.###.O#O......#.OOOO...O...##..#O.#.O.#O.###.#O....#.OO....O......#..OO.O.#.O...O.O....O.. +...O#.O..#......#...O#...O......O..........O..#..##...O.O....OO.O.#..#....#...#.#O.....#O.#O.....#.# +....#........O#.O..##OO.O....##.O...OOO.....OOO#O.#..#.#.....#.O.#......##..........OO.O#..O....#.O. +#.....O...OOO..##....OO..OO.##......O.O#...#...O...O.....O.OO.O.......OOO....#...O.##.....OO..O..... +.#.O....O..OO....O.O#O...#OO#.#....#....OOO....#O#...#...................O.#O#.O.#....O...#...#O.#.# +O...##O.#.O#....O....#O#.#.#.OO#...............#.##O...#.OO....OO...O....O#O...#.O...O..O.#.O.#...O# +.O.#........O.#..O.O#...#.....#.......#O..OO...O..O....#....O..#..O#.O....#OOO#O....#.#.#O......O.O# +.O.OOO.#O.#......O..#...........#.O.##OOOO##O.OOO#.......#....#...O..#..#..O...##.O.O.....O..#.O.... +.O..#..O..OO.#O.#O.OOO...#....#.#.O.#....OO...O....O..##...O#####O....#......O.#.#...O.#O.#O....O..O +O..#OO#....O.....O..#O..O....#O.#OOO.#..#.O#.#.O....O.#...O....O.#.O..#O.OO....#.O.#..#OO...O.O.O#.O +....#.#OO.....O...OO.#O.OO......#..###O#.#.........#O...#..O#..O.OO#OO#O.O..O#..#.#..O#.##...OOO.... +............OOO.O..#OO..O#......#..O...#....#O.....#O.....O.....OO#..OO#..O..#..O...O.O..#.##..#.#.. +..#.O.#.O.#.OO#...O.O.#O#O...OO.O..#O....O.OOO.#O.#.#.###.O...OO...........O......O..O.OO.O..#....O. +......O.#O#..................OOO..##.O#.....O.O...#.O#....OOO.#.....O.#O...O.#OO.#..OOO............. +O...O................O.....OO.O.#...#..OO....O.OO.O##O.....O...O..#....O...OOO#O......O........#O... +.#O..###.O.##O......#.....#....O....#O..#......#.#O#O..O...O#.......#O....##..##OO.O.O#...OO.O##.O.. +.#..#.......O.....#O........O.#..O....O#...........O...#....O.#O#....O..#..OO..O##....OO...#.O....OO +...O#.......OO#....#...O....O..#...##OO..O#..#O#.O.O.OO.OO....O#..##...#.##O..##OO#...#..O..O...O..# +..#..##....O.#.O...O.#.O...##........#...O####...#O...##OO.........O.O..OO#O#.###...O.O....O...OO... +##.#OO.O....#.OOO..O.....O....#O...O...OOO...O#...#....O.#O...#...O.O.#.#OO..O..#.....#O.#....##..#. +......O.O..#.#.O...#........#..O........#O......O....OO.....O.OOO##....O.O..#.#..O#.O.......#.O..#.. +O..##.....O........#.#..#.....O....#.##...O.#.....O.OO##...#OO.#...O..O##.OO.#..O..O#.O.O...O..#.... +.O....O.##O....O#OOO.#.O..#..O.O....O.O#..##..O#O#.OO....##.O#.....##.....O..##OOO..#.......O...#O.. +O...#.O........O.##.....O...OO##....##..O#...O#.O#.#..#.#O..#........#O..#O.O.O.O.O.O....##...#O#.## +.........###OO..O..#....#...............#..O..O.O.###..#OO......O.OO...#...#....O..O..#.#...OO...... +.OO.O.O..O...O......O...#...#..O.#...O.#.......O..O.......#.OOO...O..#.....#............O.....OO.... +O.OOO.O.#..#...#O...O.#.O#...#.#.#.OO...##...OO.O.O.#......O....O..O..OO....O..##..#.OO...O.#O.#O.## +O..#......#.........#...#O..O.........O#.###..OO.O..OO.O.O.....#O....#O..#...O..O..OO.....O#OOO...#O +....OO...O.#........#......#O#....O.O#....#OO#O.#.O...#........#....OO.........OO.....O.#.......O... +..##..#..O#.....#.O....O..OO##.O.....O#..#O..O...OO..O##.O.OO....O....##O.OOOO#....#...#..O.O...O... +O...#..O##.O..OO.O.O..#.#O.......O#.O.#..O.O...O.OO..#..O.....OO..O....O#O.#.#..#.O..O.......O..#... +OOO...O.#.O....#OO..O......#....O.....O..#O##...O.O.O..OOO#...#....##.OO..##...O....#..#O..##..#.... +##.O#O#........#....##.#.OO.#...O.#...##.O...#..##..O#.#.O.#OO....#.O..O..#O....#.....O.O...#O#O.O.O +....#.#O.O#O.OO...O..O#......#.#.O..O..OOO.OOOO...#O..#O..O..O.........O.#....O.#.........##O.....O. +O...#..#O#OO....O#OO#...O..#..#.#.#...O...#...#.....#.#..............O.O...#.O...OO.#..#..........O. +..O.....#OOOO.O.#...O#...#...#..O....O##.#.#..OOOO#OO...O......O..#O..#.O.O..#.#O...O.O.O#.#OOO..OO# +...O......O........##O..#...........OO..#........OO#...#...#....#O........OOO#..O#.O..#..#.O.O...#O. +.OO.#..###..#.O.O#.#...O#O.O.OO...O#....O#O#...#.O.O#.O..O.....##...#.#O.O#O.....#......O#O...##.OO. +.O.##...#O...#.#...O.......#....OOO.....#.O....O..#..O#...O..O..O...O.O..O....#....##...OOO..O#O.... +#...#.#OO#.#O.OO#.#....#...O.O#...##.O#O....##..O..#......#.#....#OO#..#O....#O#..OO...O....OO..O... +.OO#.......OO.....#.O...#O....#.....O........OOO.O.O.#.....O......#O#......##OO.#O..O#..........O... +#.#O......O.O......#.#OO........#.O#...#.O.OO.#......O#.O.......O.O.O..#.O#.#.....O...OO#O......O.O. +..O..O.O#.....OO......###.#........O#..#OO.OOO.#..O...#...#..O#.......O.#.##.#.............#O....... diff --git a/src/day14.rs b/src/day14.rs new file mode 100644 index 0000000..e744649 --- /dev/null +++ b/src/day14.rs @@ -0,0 +1,142 @@ +#[derive(Debug, PartialEq)] +enum Tile { + Empty = '.' as isize, + FixedRock = '#' as isize, + RoundedRock = 'O' as isize, +} + +#[derive(Debug, PartialEq)] +enum Direction { + North, + East, + South, + West, +} + +struct Platform { + tiles: Vec>, +} + +impl Platform { + pub fn tilt(&mut self, direction: Direction) { + assert_eq!(direction, Direction::North); + + let rows = self.tiles.len(); + for r in 0..rows { + for c in 0..self.tiles[r].len() { + if self.tiles[r][c] != Tile::Empty { + continue; + } + + // Move the closest tile in South direction here. + for r2 in r+1..rows { + let other_tile = &mut self.tiles[r2][c]; + match other_tile { + Tile::Empty => {}, + Tile::FixedRock => { + // Abort: This rock won't move, and anything further south will get stuck here. + break; + }, + Tile::RoundedRock => { + // This one! + self.tiles[r][c] = Tile::RoundedRock; + self.tiles[r2][c] = Tile::Empty; + break; + }, + } + } + } + } + } + + pub fn total_load(&self, beam: Direction) -> usize { + assert_eq!(beam, Direction::North); + + let mut result = 0; + let rows = self.tiles.len(); + for (r, row) in self.tiles.iter().enumerate() { + for tile in row.iter() { + if *tile == Tile::RoundedRock { + result += rows - r; + } + } + } + result + } +} + +impl std::fmt::Display for Platform { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let rows = self.tiles.len(); + for (r, row) in self.tiles.iter().enumerate() { + for tile in row { + write!(f, "{}", match tile { + Tile::Empty => '.', + Tile::FixedRock => '#', + Tile::RoundedRock => 'O', + })?; + } + writeln!(f, " {:3}", rows - r)?; + } + Ok(()) + } +} + +impl std::str::FromStr for Platform { + type Err = (); + + fn from_str(s: &str) -> Result { + let mut tiles = Vec::new(); + for line in s.lines() { + let mut row = Vec::new(); + for c in line.chars() { + row.push(match c { + '.' => Tile::Empty, + '#' => Tile::FixedRock, + 'O' => Tile::RoundedRock, + _ => panic!("invalid tile"), + }); + } + tiles.push(row); + } + Ok(Platform { tiles }) + } +} + +pub fn main() { + match std::fs::read_to_string("day14.input") { + Ok(input) => { + let mut platform: Platform = input.parse().unwrap(); + println!("initial\n{}", platform); + platform.tilt(Direction::North); + println!("after tilt\n{}", platform); + println!("total load = {}", platform.total_load(Direction::North)); + }, + Err(reason) => println!("error = {}", reason), + } +} + +#[cfg(test)] +mod test { + use super::*; + + static DATA: &str = "O....#.... +O.OO#....# +.....##... +OO.#O....O +.O.....O#. +O.#..O.#.# +..O..#O..O +.......O.. +#....###.. +#OO..#...."; + + #[test] + fn test_part1() { + let mut platform: Platform = DATA.parse().unwrap(); + println!("initial\n{}", platform); + platform.tilt(Direction::North); + println!("after tilt\n{}", platform); + assert_eq!(platform.total_load(Direction::North), 136); + } +} diff --git a/src/main.rs b/src/main.rs index 430b603..083b0fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day13; +mod day14; fn main() { - day13::main() + day14::main() } From 48794fe13977ae4761fd7dd921200971cfef7df7 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 19:58:56 +0100 Subject: [PATCH 112/120] Implement basic cycling Note that the east/west tilting is still wrong, but the code structure in general should now be stable: We cycle until we find that the state is actually stable (by checking a SHA-1 of it), and then return the load. --- Cargo.lock | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/day14.rs | 107 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 227 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce103b6..442c460 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ version = "0.1.0" dependencies = [ "muldiv", "num", + "rust-crypto", ] [[package]] @@ -16,6 +17,24 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + +[[package]] +name = "libc" +version = "0.2.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + [[package]] name = "muldiv" version = "1.0.1" @@ -97,3 +116,108 @@ checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] + +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +dependencies = [ + "gcc", + "libc", + "rand 0.3.23", + "rustc-serialize", + "time", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401" + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi", + "winapi", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 295b843..5b55d6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] muldiv = "1.0.1" num = "0.4.1" +rust-crypto = "0.2.36" [[bin]] name = "adventofcode" diff --git a/src/day14.rs b/src/day14.rs index e744649..127f00b 100644 --- a/src/day14.rs +++ b/src/day14.rs @@ -1,4 +1,4 @@ -#[derive(Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq)] enum Tile { Empty = '.' as isize, FixedRock = '#' as isize, @@ -19,17 +19,32 @@ struct Platform { impl Platform { pub fn tilt(&mut self, direction: Direction) { - assert_eq!(direction, Direction::North); - let rows = self.tiles.len(); - for r in 0..rows { + let cols = self.tiles[0].len(); + match direction { + Direction::North => self.tilt_north_south(0..=rows-1, |r| r+1..=rows-1), + Direction::West => self.tilt_west_east(0..=cols-1, |c| c+1..=cols-1), + Direction::South => self.tilt_north_south(rows-1..=0, |r| r-1..=0), + Direction::East => self.tilt_west_east(cols-1..=0, |c| c-1..=0), + } + } + + pub fn cycle(&mut self) { + self.tilt(Direction::North); + self.tilt(Direction::West); + self.tilt(Direction::South); + self.tilt(Direction::East); + } + + fn tilt_north_south(&mut self, rows: std::ops::RangeInclusive, source_rows: impl Fn(usize) -> std::ops::RangeInclusive) { + for r in rows { for c in 0..self.tiles[r].len() { if self.tiles[r][c] != Tile::Empty { continue; } // Move the closest tile in South direction here. - for r2 in r+1..rows { + for r2 in source_rows(r) { let other_tile = &mut self.tiles[r2][c]; match other_tile { Tile::Empty => {}, @@ -49,6 +64,34 @@ impl Platform { } } + fn tilt_west_east(&mut self, cols: std::ops::RangeInclusive, source_cols: impl Fn(usize) -> std::ops::RangeInclusive) { + for c in cols { + for r in 0..self.tiles.len() { + if self.tiles[r][c] != Tile::Empty { + continue; + } + + // Move the closest tile in South direction here. + for c2 in source_cols(c) { + let other_tile = &mut self.tiles[r][c2]; + match other_tile { + Tile::Empty => {}, + Tile::FixedRock => { + // Abort: This rock won't move, and anything further south will get stuck here. + break; + }, + Tile::RoundedRock => { + // This one! + self.tiles[r][c] = Tile::RoundedRock; + self.tiles[r][c2] = Tile::Empty; + break; + }, + } + } + } + } + } + pub fn total_load(&self, beam: Direction) -> usize { assert_eq!(beam, Direction::North); @@ -63,6 +106,16 @@ impl Platform { } result } + + pub fn checksum(&self) -> String { + let mut hasher = crypto::sha1::Sha1::new(); + for row in self.tiles.iter() { + for tile in row.iter() { + crypto::digest::Digest::input(&mut hasher, &[*tile as u8]); + } + } + crypto::digest::Digest::result_str(&mut hasher) + } } impl std::fmt::Display for Platform { @@ -104,6 +157,7 @@ impl std::str::FromStr for Platform { } pub fn main() { + const CYCLES: usize = 1000000000; match std::fs::read_to_string("day14.input") { Ok(input) => { let mut platform: Platform = input.parse().unwrap(); @@ -111,6 +165,28 @@ pub fn main() { platform.tilt(Direction::North); println!("after tilt\n{}", platform); println!("total load = {}", platform.total_load(Direction::North)); + + // Complete the first cycle. + platform.tilt(Direction::West); + platform.tilt(Direction::South); + platform.tilt(Direction::East); + + // Complete the remaining cycles + let mut previous_checksum = platform.checksum(); + for cycle in 0..CYCLES-1 { + platform.cycle(); + + let checksum = platform.checksum(); + println!("cycle {} checksum = {}", cycle, checksum); + if checksum == previous_checksum { + break; + } + previous_checksum = checksum; + if cycle % 1000 == 0 { + println!("complete {}%", cycle/CYCLES*100); + } + } + println!("total load after {} cycles = {}", CYCLES, platform.total_load(Direction::North)); }, Err(reason) => println!("error = {}", reason), } @@ -120,6 +196,7 @@ pub fn main() { mod test { use super::*; + static CYCLES: usize = 1000000000; static DATA: &str = "O....#.... O.OO#....# .....##... @@ -139,4 +216,24 @@ O.#..O.#.# println!("after tilt\n{}", platform); assert_eq!(platform.total_load(Direction::North), 136); } + + #[test] + fn test_part2() { + let mut platform: Platform = DATA.parse().unwrap(); + println!("initial\n{}", platform); + + let mut previous_checksum = platform.checksum(); + for cycle in 0..CYCLES { + platform.cycle(); + + let checksum = platform.checksum(); + println!("cycle {} checksum = {}", cycle, checksum); + if checksum == previous_checksum { + break; + } + previous_checksum = checksum; + } + println!("after tilt\n{}", platform); + assert_eq!(platform.total_load(Direction::North), 64); + } } From ddc608b0edca82e7cdd8a20e208cf96fca83fe5a Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 20:06:46 +0100 Subject: [PATCH 113/120] Add unit tests for the known data --- src/day14.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/src/day14.rs b/src/day14.rs index 127f00b..92dd3c3 100644 --- a/src/day14.rs +++ b/src/day14.rs @@ -120,8 +120,7 @@ impl Platform { impl std::fmt::Display for Platform { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let rows = self.tiles.len(); - for (r, row) in self.tiles.iter().enumerate() { + for (_, row) in self.tiles.iter().enumerate() { for tile in row { write!(f, "{}", match tile { Tile::Empty => '.', @@ -129,7 +128,7 @@ impl std::fmt::Display for Platform { Tile::RoundedRock => 'O', })?; } - writeln!(f, " {:3}", rows - r)?; + writeln!(f)? } Ok(()) } @@ -197,7 +196,7 @@ mod test { use super::*; static CYCLES: usize = 1000000000; - static DATA: &str = "O....#.... + static INITIAL: &str = "O....#.... O.OO#....# .....##... OO.#O....O @@ -208,18 +207,80 @@ O.#..O.#.# #....###.. #OO..#...."; + static AFTER_NORTH: &str = "OOOO.#.O.. +OO..#....# +OO..O##..O +O..#.OO... +........#. +..#....#.# +..O..#.O.O +..O....... +#....###.. +#....#...."; + + static AFTER_CYCLE_1: &str = ".....#.... +....#...O# +...OO##... +.OO#...... +.....OOO#. +.O#...O#.# +....O#.... +......OOOO +#...O###.. +#..OO#...."; + + static AFTER_CYCLE_2: &str = ".....#.... +....#...O# +.....##... +..O#...... +.....OOO#. +.O#...O#.# +....O#...O +.......OOO +#..OO###.. +#.OOO#...O"; + + static AFTER_CYCLE_3: &str = ".....#.... +....#...O# +.....##... +..O#...... +.....OOO#. +.O#...O#.# +....O#...O +.......OOO +#...O###.O +#.OOO#...O"; + #[test] fn test_part1() { - let mut platform: Platform = DATA.parse().unwrap(); + let mut platform: Platform = INITIAL.parse().unwrap(); println!("initial\n{}", platform); platform.tilt(Direction::North); println!("after tilt\n{}", platform); assert_eq!(platform.total_load(Direction::North), 136); } + #[test] + fn test_tilt_north() { + let mut platform: Platform = INITIAL.parse().unwrap(); + platform.tilt(Direction::North); + assert_eq!(platform.to_string().trim_end(), AFTER_NORTH); + } + + #[test] + fn test_cycle() { + let mut platform: Platform = INITIAL.parse().unwrap(); + platform.cycle(); + assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_1); + platform.cycle(); + assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_2); + platform.cycle(); + assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_3); + } + #[test] fn test_part2() { - let mut platform: Platform = DATA.parse().unwrap(); + let mut platform: Platform = INITIAL.parse().unwrap(); println!("initial\n{}", platform); let mut previous_checksum = platform.checksum(); From f65527bd04c34e8896eb91cdac46642934b4d1dc Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 20:18:48 +0100 Subject: [PATCH 114/120] Add unit tests for the other three tilt directions The input for these is manually created, so might contain issues still; the problem though is already obvious: Reversing a range is fine, but that won't make the for-loop do the right thing. --- src/day14.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/day14.rs b/src/day14.rs index 92dd3c3..2fcddb7 100644 --- a/src/day14.rs +++ b/src/day14.rs @@ -218,6 +218,39 @@ O..#.OO... #....###.. #....#...."; + static AFTER_WEST: &str = "O....#.... +OOO.#....# +.....##... +OO.#OO.... +OO......#. +O.#O...#.# +O....#OO.. +O......... +#....###.. +#OO..#...."; + + static AFTER_SOUTH: &str = "O....#.... +....#....# +...O.##... +...#...... +..O....O#O +O.#..O.#.# +O....#.... +OO....OO.. +#OO..###.. +#OO.O#...O"; + + static AFTER_EAST: &str = "....O#.... +.O.OO#....# +.....##... +.OO#....OO +......OO#. +.O#...O#.# +....O#..OO +.........O +#....###.. +#..OO#...."; + static AFTER_CYCLE_1: &str = ".....#.... ....#...O# ...OO##... @@ -278,6 +311,29 @@ O..#.OO... assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_3); } + #[test] + fn test_tilt_west() { + let mut platform: Platform = INITIAL.parse().unwrap(); + platform.tilt(Direction::West); + assert_eq!(platform.to_string().trim_end(), AFTER_WEST); + } + + #[test] + fn test_tilt_south() { + let mut platform: Platform = INITIAL.parse().unwrap(); + platform.tilt(Direction::South); + assert_eq!(platform.to_string().trim_end(), AFTER_SOUTH); + } + + #[test] + fn test_tilt_east() { + let mut platform: Platform = INITIAL.parse().unwrap(); + println!("initial\n{}", platform); + platform.tilt(Direction::East); + println!("after tilt\n{}", platform); + assert_eq!(platform.to_string().trim_end(), AFTER_EAST); + } + #[test] fn test_part2() { let mut platform: Platform = INITIAL.parse().unwrap(); From 4cc76e5ffe823352c9464c045d3990a5f75b5a3d Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 20:33:34 +0100 Subject: [PATCH 115/120] Replace ranges with explicit iterators This fixes the separate tilt methods to produce the correct results (after fixing up the expected typos in the test data). The cycle test now loops forever ... --- src/day14.rs | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/day14.rs b/src/day14.rs index 2fcddb7..171c385 100644 --- a/src/day14.rs +++ b/src/day14.rs @@ -22,10 +22,10 @@ impl Platform { let rows = self.tiles.len(); let cols = self.tiles[0].len(); match direction { - Direction::North => self.tilt_north_south(0..=rows-1, |r| r+1..=rows-1), - Direction::West => self.tilt_west_east(0..=cols-1, |c| c+1..=cols-1), - Direction::South => self.tilt_north_south(rows-1..=0, |r| r-1..=0), - Direction::East => self.tilt_west_east(cols-1..=0, |c| c-1..=0), + Direction::North => self.tilt_north_south(0..rows, |r| Box::new(r+1..rows)), + Direction::West => self.tilt_west_east(0..cols, |c| Box::new(c+1..cols)), + Direction::South => self.tilt_north_south((0..rows).rev(), |r| Box::new((0..r).rev())), + Direction::East => self.tilt_west_east((0..cols).rev(), |c| Box::new((0..c).rev())), } } @@ -36,7 +36,7 @@ impl Platform { self.tilt(Direction::East); } - fn tilt_north_south(&mut self, rows: std::ops::RangeInclusive, source_rows: impl Fn(usize) -> std::ops::RangeInclusive) { + fn tilt_north_south(&mut self, rows: impl std::iter::Iterator, source_rows: impl Fn(usize) -> Box>) { for r in rows { for c in 0..self.tiles[r].len() { if self.tiles[r][c] != Tile::Empty { @@ -64,7 +64,7 @@ impl Platform { } } - fn tilt_west_east(&mut self, cols: std::ops::RangeInclusive, source_cols: impl Fn(usize) -> std::ops::RangeInclusive) { + fn tilt_west_east(&mut self, cols: impl std::iter::Iterator, source_cols: impl Fn(usize) -> Box>) { for c in cols { for r in 0..self.tiles.len() { if self.tiles[r][c] != Tile::Empty { @@ -229,11 +229,11 @@ O......... #....###.. #OO..#...."; - static AFTER_SOUTH: &str = "O....#.... + static AFTER_SOUTH: &str = ".....#.... ....#....# ...O.##... ...#...... -..O....O#O +O.O....O#O O.#..O.#.# O....#.... OO....OO.. @@ -241,7 +241,7 @@ OO....OO.. #OO.O#...O"; static AFTER_EAST: &str = "....O#.... -.O.OO#....# +.OOO#....# .....##... .OO#....OO ......OO#. @@ -296,32 +296,27 @@ OO....OO.. #[test] fn test_tilt_north() { let mut platform: Platform = INITIAL.parse().unwrap(); + println!("initial\n{}", platform); platform.tilt(Direction::North); + println!("after tilt\n{}", platform); assert_eq!(platform.to_string().trim_end(), AFTER_NORTH); } - #[test] - fn test_cycle() { - let mut platform: Platform = INITIAL.parse().unwrap(); - platform.cycle(); - assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_1); - platform.cycle(); - assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_2); - platform.cycle(); - assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_3); - } - #[test] fn test_tilt_west() { let mut platform: Platform = INITIAL.parse().unwrap(); + println!("initial\n{}", platform); platform.tilt(Direction::West); + println!("after tilt\n{}", platform); assert_eq!(platform.to_string().trim_end(), AFTER_WEST); } #[test] fn test_tilt_south() { let mut platform: Platform = INITIAL.parse().unwrap(); + println!("initial\n{}", platform); platform.tilt(Direction::South); + println!("after tilt\n{}", platform); assert_eq!(platform.to_string().trim_end(), AFTER_SOUTH); } @@ -334,6 +329,17 @@ OO....OO.. assert_eq!(platform.to_string().trim_end(), AFTER_EAST); } + #[test] + fn test_cycle() { + let mut platform: Platform = INITIAL.parse().unwrap(); + platform.cycle(); + assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_1); + platform.cycle(); + assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_2); + platform.cycle(); + assert_eq!(platform.to_string().trim_end(), AFTER_CYCLE_3); + } + #[test] fn test_part2() { let mut platform: Platform = INITIAL.parse().unwrap(); From ff64ba7ba42de0a33b6a4fab50919aaa386db57a Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 21:03:07 +0100 Subject: [PATCH 116/120] Move the cycle/checksumming into the implementation Having it here means we don't need to copy the logic twice, which is helpful -- especially since the tricky part is that the this doesn't just settle, but rather produces a cycle of a certain length. This allows to skip the long part as soon as we know that length. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch main # Your branch is ahead of 'origin/main' by 5 commits. # (use "git push" to publish your local commits) # # Changes to be committed: # modified: src/day14.rs # --- src/day14.rs | 59 ++++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/src/day14.rs b/src/day14.rs index 171c385..e85ecd0 100644 --- a/src/day14.rs +++ b/src/day14.rs @@ -36,6 +36,35 @@ impl Platform { self.tilt(Direction::East); } + pub fn cycle_n(&mut self, n: usize) { + // Eventually things cycle back a previous state. It seems that happens + // after a few 10 cycles, so keep track of them in a simple vector. + // As soon as we found it, we can fast-forward the cycle counter, and then + // complete the remaining cycles. + let mut previous_states = vec![self.checksum()]; + for cycle in 0..n { + self.cycle(); + + let checksum = self.checksum(); + println!("cycle {} checksum = {}", cycle, checksum); + for (i, previous_checksum) in previous_states.iter().rev().enumerate() { + if checksum == *previous_checksum { + println!("cycle {} matches cycle {} ({} cycles ago)", cycle, cycle-i, i); + let cycle_length = i + 1; + let remaining_cycles = n - cycle - 1; + println!("remaining cycles = {}, cycle length = {}", remaining_cycles, cycle_length); + let remaining_cycles = remaining_cycles % cycle_length; + println!("fast-forwarding and finishing the last {} cycles", remaining_cycles); + for _ in 0..remaining_cycles { + self.cycle(); + } + return; + } + } + previous_states.push(checksum); + } + } + fn tilt_north_south(&mut self, rows: impl std::iter::Iterator, source_rows: impl Fn(usize) -> Box>) { for r in rows { for c in 0..self.tiles[r].len() { @@ -171,20 +200,7 @@ pub fn main() { platform.tilt(Direction::East); // Complete the remaining cycles - let mut previous_checksum = platform.checksum(); - for cycle in 0..CYCLES-1 { - platform.cycle(); - - let checksum = platform.checksum(); - println!("cycle {} checksum = {}", cycle, checksum); - if checksum == previous_checksum { - break; - } - previous_checksum = checksum; - if cycle % 1000 == 0 { - println!("complete {}%", cycle/CYCLES*100); - } - } + platform.cycle_n(CYCLES-1); println!("total load after {} cycles = {}", CYCLES, platform.total_load(Direction::North)); }, Err(reason) => println!("error = {}", reason), @@ -344,19 +360,8 @@ OO....OO.. fn test_part2() { let mut platform: Platform = INITIAL.parse().unwrap(); println!("initial\n{}", platform); - - let mut previous_checksum = platform.checksum(); - for cycle in 0..CYCLES { - platform.cycle(); - - let checksum = platform.checksum(); - println!("cycle {} checksum = {}", cycle, checksum); - if checksum == previous_checksum { - break; - } - previous_checksum = checksum; - } - println!("after tilt\n{}", platform); + platform.cycle_n(CYCLES); + println!("after cycle\n{}", platform); assert_eq!(platform.total_load(Direction::North), 64); } } From afbea5acf6ca23318d3ae559fb9bfa560ca858b2 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Tue, 19 Dec 2023 21:26:48 +0100 Subject: [PATCH 117/120] Day 15, part 1: HASH. --- day15.input | 1 + src/day15.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 ++-- 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 day15.input create mode 100644 src/day15.rs diff --git a/day15.input b/day15.input new file mode 100644 index 0000000..f3b0d56 --- /dev/null +++ b/day15.input @@ -0,0 +1 @@ +mpp=7,nzr-,lms-,lq-,lhqrxp=8,psb=2,jznz-,hf-,kpns=8,gq-,lm-,hlgzpp=5,gp=1,dzd-,xx-,hm-,kvz-,lzls=1,dbl-,dzd-,hcgd=7,lff=2,gbvzq=5,lql=7,hvk-,mpp=6,tx-,rg=4,lzhv=8,pdd=9,ds-,tcr-,bhm=6,cnn=8,ntms-,bkg-,hfnk-,pvf=1,tzh=5,mp-,zhdr-,nvj-,dfl=5,ccm=5,gc-,vmrr=5,zn-,kfq-,ts=2,tf-,pz=8,gp=2,hs-,lqrlg=8,rs-,pdm=1,kvbq-,sdk=1,vr=8,cls=4,fhzbjq-,nqn-,dlssls=4,ft-,pdd-,fphd-,sjg=7,jt=9,kl-,lps=7,npr-,jdk-,jj=1,dxd-,qjngd-,xjp-,btlt-,btm=3,gjhz-,bg=3,bjn-,bkd=2,clb=6,lq=9,jvx-,pvpn=3,dqzdbx-,tsj=1,vcjdc-,jgkzf=7,jtm=9,rxsj=1,xr=1,kvj-,kh-,fkz=7,dvg-,njzgjp=4,kfz=7,dm=6,zmql=7,gr-,nmv-,fpfzc-,sr=7,lvfd-,chs-,kbf-,ds-,srl-,rxcfx-,nbp=8,qm=8,xzf-,nbxlm-,nk=6,gmn-,nbp=7,dcj-,zgnp-,zmg=5,jznz=1,tnm-,vrhb-,ljvv=4,lcm=1,zkx=3,fpfzc=8,ll=5,lmktdb=5,hfnk-,ksf-,ml-,kfp=7,zdnr=9,cv-,vl-,jgkzf=2,cg=1,srp-,lms-,cxfh=3,vq-,mgt=7,sjg-,mmgq-,qdx-,vb-,xvmb-,qjngd=3,dxd=7,jxb=4,xhn=3,vrcrz=5,zsvhrh-,tmvns=5,knb-,bbng-,fn=8,nln=6,mxm=3,hb-,qr-,sp=5,pz-,gccsrh-,hm=2,btlt=7,xtg-,dbl=1,nbxlm-,gsq=3,gf-,zlg=6,bjn-,db-,kvbq-,lr=4,ht-,fljt=2,bnvb=9,vv=7,vrhb-,hggm-,ht=2,bbng=4,zxt=7,vzf-,dvl-,nq-,pdm=3,xv=9,vq-,rxcv=6,cf-,kl=3,btm-,fnxn=7,ztv-,vrq-,srl=6,njzgjp-,nl-,vrhb-,cgr=2,fz-,hpvp-,nnpd-,jffc-,tv=3,hf=8,bl=7,xdqs-,kfp=3,bljv-,sr=7,vz=6,cg-,fr=1,tjf-,mdcjcv=8,ksd=6,qd-,lc-,qncs=4,dn-,zn-,jznz=5,fx-,ch=3,tj=9,hsr-,qxrlr=5,pmr=3,ms=2,njzgjp=8,rbjmn-,kl-,lms-,rmc-,gbvzq=7,kh=8,dcj-,tjf-,btm=6,zt=8,dj-,fr=8,zzz-,mf=3,cxfh-,jc=6,gf-,lr=3,kpnltb-,fcb-,bzkc=1,kpns=6,sr-,zsvhrh=8,thq-,phfgr-,gvtcn-,hlgzpp=2,vz-,bhm-,fhpnc=3,tg-,qncs-,btm=1,xdv-,qngk=1,lps=2,qrd=6,ksf=2,zf=3,hnd-,thl=3,bpv-,lnhp=8,vtm=8,nc-,sjg=5,rm=3,pdm-,zvf=1,pzjs-,hmhs-,dshp=8,vr-,hb-,fn=8,hvqmc-,hsbtx-,kfq=4,qnh-,kpns=4,slk=1,hvxdf=4,hgh-,fc=8,tkk=1,pvht=7,dvl-,ntms-,jfx=2,cztdj=7,lq=2,pgckd-,jtm=9,smh-,fxvg-,dcj-,jqs-,hsbtx-,mlnd-,msm-,nnpd-,xng-,lz-,nbxlm=7,jgzst-,tvzv=7,jtm=4,bkj=7,nqn-,rjqxh=3,zhx=9,mlfj-,rz-,drl=9,gf=4,fn=1,xc-,rb-,dvn=8,bcr-,hq=8,xbh=4,jmnh-,xx-,nqn-,gf=9,nvj=5,vvgx-,mgt-,dvq-,tjf=3,ljvv-,phfgr=3,ljvv=8,ngx=9,vbbdk=4,bnh-,ccfj=5,fhpnc=4,xvmb-,fz-,cg=6,qt=5,cj-,lg-,th-,drl=9,jgzst=3,jmnh=3,rjj=5,vrhb-,mfdp-,hqc-,lmmc-,tzh=5,mmgq-,hx-,nc-,qncs=5,bzkc-,nbq=5,hfn-,mlfj=9,zf-,vrc-,zhdr=7,drl-,bl=7,mtbflg-,xvnr=5,jdk-,kvbq=7,xlb-,tnkv-,lc-,vvgx-,gr-,mpp-,zl=3,kfp=6,bnvb=3,rgl-,xlb-,qtm-,hvk-,tnkv=2,vmrr=1,df=6,xgd=7,fd=8,kh=5,fhpnc-,jffc-,cl=2,hzr-,bljv-,vlc-,vv-,grm-,xhn=7,zd-,xlb-,dm=7,nln-,lcm-,rhn-,blf-,lth=3,lth-,rz=2,hsbtx-,lcqz=9,gsq=9,mdlz=7,dvjdr=3,kpns=5,lzhv=2,nqn-,mgf=1,zvl=8,dxd-,cbkk-,gm-,zzz-,rhv-,sp-,pmr-,gbvzq-,gzt=1,rkkd-,bkj-,tqhs=7,hfnk-,nq-,hlv=2,tgh-,zlsd=4,vb-,mx=2,gq=2,bdkp=4,pk-,fnxn=5,fhzbjq=9,psb-,qdq=2,fljt-,lthlq=1,nlg=5,rg=8,ms=5,zxt-,bqq=2,xv=3,mxm-,gvf-,bzkc-,kpns=4,fr=4,pvf=6,mt-,kr-,vp=5,hfnk=9,jfx-,bljv-,grchdx-,kvj-,nbq-,hzr-,fz-,pds-,lqrlg-,nq=5,nth=1,btlt-,tqb-,lg=9,vfcz-,qngk-,msm=9,npr=4,nmv=3,dqzdbx-,jjhtxb=1,djdd=6,nq=8,fmbv=2,tmvns=9,zmg-,qdq=6,rv=9,qncs=9,zd-,rg-,qd=9,cnn-,mx=8,md-,tnkv-,rm-,rdq=6,xr=2,hs=6,lthlq-,kn-,lv=3,jg=6,drl-,bbng-,md=9,dvn-,pvgstv-,tnqhlk-,dvg-,ccfj-,rb-,mt=1,psb-,btlt=6,vfk-,zdnr=5,kmrzk=7,hzqh=6,fpfzc-,njzgjp=8,fnhpf=3,kh=5,xc=8,jmnh=9,zn-,rmc=3,tfmq=5,kz-,fn-,vx-,kx=3,hqc=8,fljt-,fxvg=9,msm=9,fhpnc=4,clnxp=5,rfkbqp-,cplm=1,nmv-,vp=9,vl=8,sp-,fm=4,tmn-,lz=7,gzdxh-,mgf-,vfcz=5,lc-,slk-,gsdvk=6,fn=9,ccfj-,qn=5,ptxfn-,ztv-,hf-,ktd=9,tf=6,qt=1,nlg-,gjbm=1,dzd-,rxsj-,lth=9,qqjc=1,mfnm-,rjqxh=3,kvj=3,lms=9,lc=9,smh=7,crr-,zlg-,vd=8,hf-,kmrzk=1,mcx-,rjqxh=8,drl-,mqc-,dxd=7,ggsx=1,tvf-,hv-,nvj=5,tp=1,lt-,fk-,kfz=5,dbl-,kfp-,hvxdf=2,gvtcn=2,phfgr=2,ggsx-,rb=4,jf=1,gs=5,hvk-,fphd-,lms=3,qr-,hrq-,gm=5,pgckd=4,zlsd-,tf-,jlp=5,ktd=8,zxt-,ds=3,tqhs=9,rtxt=6,gp=4,nlg=8,gvf=6,pgltk-,thxnd-,zx=7,qjngd-,jgkzf=4,dv=9,dvjdr-,jt=4,fnxn-,fx=1,nl-,cgr-,msm=4,hch-,cj-,vb-,ft-,gr-,rg-,bkd=4,thl=2,sp-,hf=3,jf-,pgckd-,xb-,hggm-,rhv-,hrq=6,xnx=2,fljt=7,rmc=8,ssv-,jqrb-,hggm=4,gt=5,rxcfx=3,dvg=5,zjhsg-,fd-,thxnd=1,rgl-,grchdx-,tfmq-,tqhs=2,rxcv=3,rl-,pvgstv=7,cg=8,bg=5,lnhp-,blf-,gr=5,nqk-,fm-,sp=7,hsbtx=8,grchdx=1,tkk-,mfdp=4,jvg=2,fj=3,tt=6,hq-,thl-,fzt-,tv-,mdcjcv=7,lt-,tqb-,qnh=2,lthlq-,fhzbjq=8,mx=2,vz-,hlv-,hfn-,gc-,jsdb=5,kx-,tnm-,jg=5,sz=3,bts=5,kqb-,gtt=3,hsr-,zvl-,cbkk=6,jf=7,kpns-,zl=5,mp-,kfp=4,nx-,ssv-,nqk-,ccm-,gbvzq-,pds-,hpvp=1,bg=7,kv=4,sxnj-,hgc=4,gm-,dc=5,mn-,zkl-,thq=6,ccfj-,fnbgjj-,hnd=6,hvxdf=7,dvl-,xng-,kd=4,rjj-,lzhv=1,pvht-,kfq=5,nnx=5,dvjdr-,gtt-,vfcz-,btm-,jlp-,nzq=2,zzz-,mfnm=5,fljt=8,lzhv=4,qf-,zdnr-,clnxp-,dshp=2,ktd=9,pf=1,zhx=1,lmmc=3,jt=2,rsps=1,xj-,glrql=7,pk=5,pvht-,jffc=5,rlsl-,hcgd-,hcvsn=8,kh=7,xl-,cl-,rsps=2,npm=9,sm-,gf=3,vq-,tsj=6,zxr-,rrg-,bts=3,drt-,hvxdf-,tkfcrj=4,phfgr=6,jffc=9,fm=4,jt=6,smh=5,kj=2,qncs=9,crr=4,hj-,kx-,sz=7,mpp=2,nbq-,ztv=3,hm-,nshbkn-,qrd=2,pdm-,kz=5,lmktdb=8,vx=3,jg=6,ms-,pvf=8,nxm=7,df=4,tkk-,kmrzk=4,qncs=6,ncvj=6,tnkv=8,phfgr-,vrc-,dvg-,jqs-,ff-,srl-,kn=7,xlb=5,kfz=1,kx-,lcm=9,lmlbf=7,hch-,rfkbqp-,vb=6,rmc=9,rkr-,dfl=4,vcgxs=3,npm-,vrb-,dvn=5,kfz-,vr=3,dxd-,scb-,slk-,pdm=5,xhn=1,sdk-,jxb=3,hsr-,hf=8,jznz=9,lm-,ssv-,pdd-,bv=4,jj-,dcs=1,hvxdf=4,vhrcbm-,bg-,ds-,xc=3,nln=6,jfx-,ncvj-,xr-,kfz=4,fr-,vb-,fpfzc-,vv-,jssb-,zjhsg-,qdq=3,df=4,pxzc-,dc=3,fpfzc-,tmb=7,zgnp=8,xvmb=1,fp=4,jj-,tkk=7,grm-,mgt=6,tnkv-,mqc-,bkg=1,njzgjp-,fphd=9,fljt-,vt-,pvht-,lth=2,ngx=8,tbvx=9,gzt=7,hqc-,xpkljm=3,kr-,mcx-,lzls-,rhv=4,tnm=5,rxp=8,tg-,xhn-,slk=6,xbh=2,fm=4,mlfj=4,rg-,fz=2,vfk-,pf-,df=1,cf-,rhn=2,tp=1,kt-,dj-,lms=2,lq=6,nln=3,nzp=7,bkj=1,hnd=7,gsdvk-,qxrlr-,bg=3,zsvhrh=8,rtxt-,dvjdr=2,nln-,lps=3,tnqhlk=6,nxm-,bkj-,jt-,kgb=5,jznz=3,dcj=4,bcr=7,bb=6,xr=5,bb-,knb-,crr-,ksd-,cplm=5,tgh-,ghqj-,kr=6,dvg=5,vdgn-,zsckf-,nzp-,gs=9,ppk-,ksd-,ksf=3,ngx-,bfdbb-,kpnltb-,grfv=4,blf-,ztd=5,jpj=1,nj=8,bq=8,tnm-,jzs=2,rg=5,psb-,hcgd-,bzkc=9,gc-,xzf=2,jfx=9,sjg-,mlnd=1,sjg=9,lql=7,hfn=3,zdnr=3,nzp-,nbxlm=3,rb=4,dv=5,xv=8,dshp=2,mxm-,qngk=5,blf-,jffc-,cplm=5,kq-,lmmc=5,gs=8,jzs-,hcgd=3,chs=1,xvnr-,fxvg-,vfk=3,dvn-,gc-,zhx=9,hgc=6,tp-,vdgn=9,nqk=6,srp=7,hvk-,qsg=8,gccsrh=5,hggm=8,xlb=2,kv=7,df-,vz-,lff=1,pr=9,rmc=5,pds=7,ccfj-,sgs=5,dcj-,xgd=9,zn-,df-,kt-,hcgd=6,knb-,clb=7,nl=8,xttmp=6,hx=6,rm-,cxfh-,ngx-,lff=7,dj=7,kpnltb=4,fnhpf-,rvq=4,hcvsn=8,hs-,vmrr-,tvzv-,clb=1,fc=8,vthzt=2,jffc-,qr=8,kvj-,bhm=5,mgf=9,sp-,xng=7,lmmc-,mp-,kxmlkn=7,clb=4,vd=8,fx=5,vt=2,slk-,gccsrh-,fxvg=6,gccsrh=6,xr-,fxp-,fbh-,rhn-,bts=4,db=5,nbp-,kpg=6,btm-,bsp-,fj-,kh-,tvdl-,jssb=9,gb=3,bb-,qd=6,mf-,zxr=9,grchdx-,nth=2,kvz-,bkj=3,jlp-,nnx=6,nxm-,xx-,xc-,bljv=8,grm=4,hzr=9,kj=7,xbh=2,rtxt-,glrql=3,vfk=4,clb=3,mlfj-,dlssls=6,gt-,ccm=9,fxvg=4,thl=4,vz-,jt-,ml=2,tsj-,fkz-,mfs=8,hnd=8,pdd-,tnm-,jssb=2,pjv-,rb-,rmc=8,hch=8,qf=1,jlp=3,dvjdr-,zf=2,dzd-,hb-,vlc-,thxnd=8,kgb=7,gvtcn-,dlssls-,xttmp-,pxzc-,dv-,rdq-,lv-,chs=1,hq-,ntms-,hlv=6,nh-,rjqxh=8,ft=6,jj=5,nnx-,cq=4,zf-,vz=1,gp=6,zsckf-,lqrlg-,kxmlkn-,nq=2,dvjdr=9,pgckd=2,tvf=2,zxr-,thl=2,jlbm-,ztv=1,xnx=3,tvzv-,zsckf=9,xzf=9,kd=5,kz=8,ngx-,gzt=6,zxr=7,cbkk=2,hggm=7,dm-,hv=1,kvbq-,blf-,djdd-,rp-,zsvhrh=6,jj=5,jmnh=5,lz=9,zl-,vt=8,vhrcbm-,pzjs=8,cq-,jsdb-,vd-,hlv=5,nshbkn-,ntms=6,bv-,gbk-,vzf-,kc=3,lv=8,fkz-,rlsl=8,tg=1,pds=5,rm=7,jsdb=8,zd=3,bl=1,vthzt-,hggm=1,xzf-,qf-,ms=7,xc-,jqs=9,qncs-,lzhv=8,kx=3,hj=7,vz=5,pp=7,gb=9,dshp-,nc-,rsps=1,qjngd-,fjqc-,rtxt=9,gzdxh=3,ksd=2,cbkk=9,zkx-,kx-,hmhs=8,hcgd-,zkx-,hsr=7,jlp=1,rrg-,mlnd-,hcgd-,qnhgvl-,vrhb-,cplm=2,lth=3,lt=6,gs-,hggm=5,gp-,vd=6,tmb-,qtm-,zd-,ccfj=8,fhpnc=5,lth-,rfkbqp=3,cl=8,dc=8,rm-,kg-,bnvb-,jmnh-,tvdl-,fd-,lff=2,lrvb=3,gp-,rjj-,psb=4,bzc=9,kz-,fx=8,dj=1,hb=1,zkl=5,njzgjp-,rxsj-,vrq=6,jgzst-,kfq=8,fphd-,rxcv=8,gzdxh-,pjv-,fphd=1,jsdb=1,mcx-,vx-,lmmc=9,rs=2,vx=9,hgh-,ts=5,vrc-,nzr=2,gcf=4,ks-,hg-,gsq-,mgf=3,mgf=7,pgckd-,pgckd-,jpj=2,psb-,fljt=4,thq=2,tf-,rkr=1,ccfj-,dbl=1,dc-,nqn=8,gjbm-,qngk-,btm-,xc=6,tkfcrj-,rvq-,gbk=4,ll=3,zn=5,xtg=8,mmgq-,fxp-,ksd-,tvzv=1,scb=2,zgnp-,lps=5,fkz-,vdgn=9,zmg=9,vvgx-,fljt-,rxsj=5,ms-,fq=6,pvgstv-,zkl=3,bkg=6,jzs-,mfs=8,zkx=6,xqx=8,jmnh-,xlb-,tnm-,ksf-,hv-,rrg=8,tvzv=1,rz=8,lcm=2,sqvq=2,kq-,ckzq=6,nc-,tbvx-,vd=8,lm-,nln-,btm-,ccfj-,gbvzq-,nnx=1,sp=3,qn=8,nj-,ml=5,ngx=4,rb-,zlg=8,zjhsg=9,bs-,fphd-,sgs-,bhm-,rv=7,ggsx-,bdkp=8,pmr-,hcgd=3,gtt-,tnkv=9,nl-,gccsrh-,qr-,vrb=1,zn=4,lff-,bhm-,rl=5,vx=3,zmg=4,xr=5,nqr-,tmb-,vfk-,qxrlr-,ktd=5,btlt=7,fs-,ddbxf=5,pvht-,vzf=2,zd=7,hv=4,hggm-,nbq-,xbh=2,th-,mx=9,ktd=6,dqzdbx=9,kg-,qr-,lpmh=9,xx-,gzdxh-,th=8,vfk-,zxr-,lmktdb=5,jmnh-,fjqc-,nqn-,mfs-,xv-,lhqrxp=3,pn-,gvf=5,rbjmn=5,pxzc-,nbxlm-,gvtcn=1,tbvx=5,cnn-,vrcrz-,hsbtx=8,drt-,mfdp-,vt=2,pr=9,dcs=4,cq=1,zsckf-,smh-,fx=5,hg-,hj=1,rz=5,nzp-,zxr-,sz=1,hg=6,fq=4,lmlbf=3,cf-,jdk=1,qdq-,cgrv=5,dxd-,dvn=7,fnhpf=1,hcvsn=5,zjhsg=4,bv-,fnxn=6,tkk-,vp=2,gq=3,bv=7,lps-,ggsx=3,fnxn=2,nq=1,hj-,nth-,sm=3,sxnj=8,jxb=7,tqb-,jpj-,dvn-,xng=7,sdk=7,fzt-,hqln-,vt=2,bzc-,kc-,nh=4,kmrzk=3,hm-,jfx=8,cv-,rtxt-,mdcjcv=2,dbl-,zsvhrh-,lrvb=2,pf=8,xr-,jlp-,qsg-,tcr=2,nqn-,vmrr=2,sdk=6,nxm=4,xqx=8,gf=4,zlsd-,hs=1,tvf-,rz=3,xtg=1,tnqhlk-,kxmlkn-,gzt=5,kl=3,smh=2,fq-,sz-,fnhpf-,hmhs-,dvq=6,kvz=2,vt-,tfmq=2,vrhb=1,tqb=6,hzqh=6,dp=6,nlg-,lcqz=1,dlssls-,lqrlg-,hggm-,mfdp-,hm=9,cxfh=3,vv-,rkkd-,nbp=1,rhn=3,gr-,npm-,lpsr-,rjj-,xng-,bnh=7,pdm=4,lm-,jvg-,gvsr=7,mn-,tsj=2,grfv-,tg-,zzz=7,cq=4,jzs=5,nh-,zhdr=1,tg=4,ll=6,rlsl=9,hlgzpp=1,kg=3,rs=6,hgh=8,ztv-,vx-,pvpn-,gr-,pjv-,tvf=6,md-,dbl=4,ddbxf-,tnm-,nzq-,rxcfx-,gvtcn-,xr-,xb=8,vbbdk-,cplm=2,fd=9,cls-,drt-,tjf-,md=3,lmmc=9,hv-,sr-,vfk=4,hrq=5,bzkc-,cj=5,qngk-,thq-,nlg-,lps-,lcm=3,lt-,grfv=7,tx=8,zkx-,scb=8,jlp-,rxcfx=1,jdk=3,dvl=2,pf=4,mlfj-,nktx-,tkfcrj-,vfcz-,nzp=8,lpsr=3,hsr=8,ddbxf-,pxzc=3,tf-,rxcv-,mfdp=9,qnhgvl=5,pf=1,dv-,rv-,rm=3,tkfcrj-,mts=2,fk=7,qf-,vlc-,ztd=1,grchdx=7,rmc=7,rxcv-,xttmp-,rjj=5,srp-,xc=4,pvpn=5,cgr-,thq=5,cgr=8,zlsd-,thl-,qtm=5,rvq=4,ft-,fzt-,fn-,bhm-,qvhkp=4,jc-,nqn-,crr=2,zmql=2,qsg=1,bjn=1,sz-,cv=3,lm-,cj=1,jqfmp=1,hcgd=8,rg=3,jvg=4,fq=7,pdd=8,kfz-,tx-,zf=5,gbvzq=7,jjcpm-,ts-,kfq=8,bzc=4,dvjdr-,tx=1,fz-,fs-,zf=1,jh-,jc-,hvqmc=8,thq=5,lmktdb=5,zzz=1,gsdvk=5,grchdx=7,jsdb=5,tbvx-,nj-,jgzst=7,cq=4,nx-,jvg=6,gvsr-,tfmq-,mn=2,hzr-,pzjs=6,fcb=5,jlbm=1,lnhp-,lnhp=3,grchdx=8,bs=1,gmn-,jxb-,tvf-,xttmp=1,bnvb=2,gp=4,hq-,mn-,tvdl=6,zlg=4,vb-,tmb-,clb=8,kqb-,gjbm=9,qncs=8,thq-,fd-,fnbgjj=1,gsdvk-,rg=5,lvfd=8,tzh=9,rdq-,zkx-,xpkljm-,pr=3,mxm-,nqn=4,hs-,nnpd-,tv-,kfq=3,tp-,fxp-,cv-,btm=1,ksf-,pf=3,hgc-,bbng-,hpvp-,kz=9,xl=2,ksf=3,fbh=7,dfl-,kxmlkn=2,nk-,ksf-,ksd=4,gp=3,hlgzpp-,crr-,kr=2,bkg=7,mx-,rm-,zmql=2,bfdbb-,th=3,crr-,vrhb-,clnxp=8,qr-,xttmp=5,tjf=5,rxp-,rjqxh-,cv-,vrq-,jqs=9,xhn=7,nhb-,cl-,bl=7,gbk=2,cq=6,dbl-,gvsr-,jt=8,qsg=3,rlsl-,hgh=4,ht=4,vr=2,tqb=2,fm=7,tnm-,bdkp=6,tmb=8,lpmh-,vz=7,bsp=6,bkg-,fcb-,clnxp-,lg=8,fx-,qnhgvl-,kl-,db=2,knb-,hq-,lr-,ljvv=3,bv-,vz=3,xlb=7,kpnltb-,gsq-,pgltk=9,bkj-,lps=9,rb=4,jjhtxb=6,zsckf=2,gr=5,kz=6,hlgzpp=9,kv-,xtg-,xvmb=4,rs=3,fxvg-,tvzv=4,kfp=6,gsdvk=5,gzt-,jpj-,vrhb-,hs=7,kqb=3,cx-,sgs=2,rp=2,gr-,ztd-,qjngd-,xbh-,sqvq=2,dxd-,mlfj=1,ptxfn=6,bkg=5,btlt-,mdlz=9,jqrb-,nbq-,npm=8,kpnltb-,pgltk=3,cf-,zkl=5,ft=7,cf-,jjhtxb=7,qt-,fc=2,zjhsg=7,npr-,dvq=2,hb-,nln=2,zmg=3,hsr-,nbp-,mx=1,npm-,pdd=9,zzkc=7,nbq=1,jqrb-,kqb-,vz=2,nk=9,hs-,vrhb=7,hpvp=3,kj=1,zdnr-,gvtcn=5,zxt=3,bkd=8,zkx=1,gp-,gsdvk=8,nqk-,jlp=5,vhrcbm-,lpsr-,clnxp-,lm=3,jjcpm=9,nlg-,clnxp=8,vbbdk-,xlb=6,hvqmc=3,hg-,kfp=7,fx=8,lcqz-,djdd-,srl-,tt-,cl-,pz-,kl=2,tkfcrj=6,kvj-,kbf=1,nktx=3,fphd-,vd=6,bnvb=6,pdm=1,rp-,ds-,nl-,fn=4,mxm=1,rvq-,nh=1,qtm=4,fnhpf-,xttmp-,gc-,zd=9,szp=6,vdgn=3,hg-,gzdxh-,mlfj-,pgltk=1,cgrv=5,gsq-,hf=3,qdx=6,kx=4,vzf-,lmktdb-,gvf-,xtg-,hsbtx=2,gsq=4,rjqxh-,gvtcn=7,ztv=3,lmktdb=4,npr-,pgckd=2,nqk=3,xpkljm=8,ntms-,ks-,bs=6,vlc-,knb-,mfs=3,xvmb=1,hggm=5,fk-,zn=1,xpkljm=3,tmvns=5,zdnr-,tcr-,ks=8,vmrr=6,zgnp=8,dvl-,zhdr-,dvg-,mxm-,hfn-,vql=4,mts-,pvht=3,bhm-,pgltk=5,hgh-,jqrb-,bnvb=3,jh-,cbkk=1,vlc-,jdk-,bzkc-,chs-,qt-,kh=6,gs=2,tnqhlk=7,qxrlr=7,bs=1,qx-,dqzdbx-,gt-,jffc-,ztv-,tqb-,lp=5,gzdxh=3,tqb=8,tx-,bkg=8,gsq-,dvjdr=8,cbkk-,xvmb-,gm=3,lzls=3,sgs=6,fpfzc=1,tfmq-,lps-,vrq-,kc-,tnkv=5,rtxt=2,nk-,kvbq-,qxrlr=4,zvl-,sxnj=7,mts=6,gmn=3,zxr=5,hmhs=2,tvdl=1,fc=9,rfkbqp=2,lv=6,xlb-,kbf=8,vcgxs-,vvgx=2,rlsl=7,ztd=1,tkk-,pp=5,thq-,zl-,vvgx=4,msm-,gb-,sz=1,nk-,nl=8,lm=7,nl=4,rxcfx=8,mxm-,jxb=3,ztv=3,gc-,szp-,fr-,fk=2,mfdp-,zt-,tfmq=2,hpvp=8,fq-,bs-,rb=7,fnxn=9,xv-,lmmc-,bts-,jqfmp-,hfn=1,thl-,hvxdf=1,bs-,dj-,fhpnc-,qt-,pvpn=1,tjf=5,rb-,gtt-,vthzt-,gzdxh=3,vtm-,lv=9,lpmh=8,hsr=8,lpmh-,zdnr=9,hghph=4,lv-,ngx-,zmql=7,xnx-,cg=1,kfq=4,vp=4,hpvp-,pn-,vq-,bnh=7,dzd=2,ztd-,hldlq-,vthzt-,hqln-,tfmq-,hmhs=7,bts=8,qnh=1,xqx=6,clb=3,jssb=4,jvg-,gmn=5,hs-,vp-,qngk=9,ptxfn-,dvn=3,tqhs=8,fd-,rtxt-,mxm-,gbk-,bqq-,ghqj-,ml=5,xvnr-,rg-,rkkd-,lc-,gf=6,jjhtxb=5,vx=2,kd-,mt-,vthzt-,rgl=1,bcr-,kq=1,grm=3,fnxn=7,mmgq-,hsr-,npm-,hzqh=4,npr-,lql=9,bnvb-,ggsx-,rrg-,rkr=9,nqn=8,bkd=3,sdk-,jfx-,lm-,qt-,zd=5,dj=3,xv-,dzd=2,nbp=8,tnqhlk-,fn-,lrvb-,vrc=5,bts=5,lms=9,hx=5,nqr=3,nmv=5,rrg=3,gr-,zsckf-,gbvzq-,npr-,gcf=6,qd-,pvf-,fgdh=1,nc=6,rdq=6,hv=8,mdlz=7,ff=1,kqb=5,vhrcbm=4,hgc-,blf-,pzjs=1,zn=2,pvpn=7,lt=1,gcf=4,qnhgvl=1,kg-,ztd-,fn=2,lmmc-,lthlq=6,mqc-,hg-,rmc=5,fxvg-,sdk=9,ddbxf=5,qrd=3,zlsd=5,nzr=2,hx-,dcj-,kfz=4,jssb-,kvz=5,hx-,thq=3,pdd=8,hvxdf=6,fbh=3,dc-,mtbflg=8,dshp=4,pz=4,lv=7,mtbflg=8,blf=6,jgzst-,dv=8,lqrlg-,hcgd-,ms=7,mfdp=4,kc=9,zd=7,qjngd-,kx=9,tcr=2,xtg=5,hgc=3,pgckd=4,mmgq=8,rvq=6,vp-,lt-,vql-,fxp-,zkx=1,ts-,lq-,hcgd=2,qx-,bkj=4,crr=3,zsvhrh=6,tnm=2,mk=8,xr-,xr=5,hgc-,fhzbjq-,fnbgjj-,hpvp-,hgc=4,cgr-,bljv-,ptxfn=4,vx-,kz-,dvg-,ssmm=4,ksf=9,bbng=7,nqr-,sz-,thq=8,pvpn-,ssmm-,ch=7,gjbm-,qn=6,zx=2,zvl=2,slk-,jzs=9,qm-,cj=8,qnh-,nbxlm=2,thxnd-,xr-,ztd-,hj=5,pr=4,gtt-,lpsr-,cbkk=4,pjc=5,lz-,lc=2,hvqmc=3,fhpnc-,bts-,fn-,fnxn-,qx-,jpj=2,ptxfn-,hcgd=3,xc=4,kgr-,btm-,sm-,vb-,tsj-,vt=5,db-,hzr=3,df-,xhn-,rm-,nqn=9,gvf-,kvbq=7,dp=6,xjp=1,xdv=8,nc=5,tbvx-,xbh=4,kvz-,tjf=5,kh-,vv=6,rxsj-,cls=8,kmrzk-,zf-,bjn=5,rkkd-,lcm-,fn-,hfnk-,hfn-,zkl-,bhm-,nln=7,kn-,gvtcn-,bjn=1,kvz=8,rkr=9,vcgxs=3,qnh-,nbp-,clnxp-,mdlz-,dshp=9,gccsrh-,pgckd-,kpns=5,kgb-,jssb-,fs=7,cj=4,md=1,zmg-,jssb-,vl-,mmgq=6,fxp=6,zd=9,nzr-,cx-,ppk=1,vthzt-,bnvb-,nzp=5,nbq=6,pnzs=9,vfcz-,ppk-,qngk=2,hvxdf=9,zmql=4,zgnp-,qt-,ktd=9,vlc=6,jc=9,lrvb=7,sxnj-,hs-,pjc=4,mk-,cq=2,bpv=2,jmnh=1,kn=5,ggsx-,qm=9,tkk=2,hnd=4,gvf-,zlsd=9,drt=4,db-,mdlz=7,hlgzpp-,zvl=8,thq=4,ksf=7,nzr=3,lps=4,nqr-,dcj=2,gcf-,vcgxs=7,fx-,mn-,ts=8,gjhz-,blf=7,lg-,jjcpm-,pnzs=1,pvgstv-,bsp=3,ds=1,sr-,dvq-,ddbxf-,kpnltb-,lzhv-,kx=1,fjqc-,kxmlkn-,fr-,jtm=7,th-,rxp=9,hsbtx-,hg=3,nj-,ds-,mt-,tp=6,ntms-,lqrlg-,ts=4,nshbkn-,mfnm-,pmr-,ktd-,hggm-,pgltk=9,jfx-,kpg=4,tgh-,vb=5,jfx-,hgc=9,zt-,nbxlm-,fnhpf=7,ccm=6,vfcz-,gjbm-,tp-,vp=8,zmql=5,vdgn-,zvf=1,vrq-,npm=4,xdqs=7,ckzq-,rgl=9,pp-,tkfcrj-,bqq-,kfq=3,cgngq-,qqjc=1,nshbkn-,mf-,fxvg-,fphd=6,ff=4,jffc-,nqn=8,vt=5,tzh=6,fkz-,tj=8,nbp=2,ms=4,kz=3,cv-,tp-,fzt=4,kj-,kj-,vrcrz-,bs=2,lpmh=2,sgs-,xdqs=5,zvl=8,hzr-,zvf=8,sqvq-,drl-,vfk-,rs=2,qdq=2,pjc=7,pgltk=3,fcb=1,rhv-,jxb-,pf-,ntms-,fgdh-,smh=8,njzgjp-,pf-,hgh=8,vrhb=2,bv-,glrql=8,vd-,jgzst-,lthlq-,ddbxf=8,kx=8,mmgq=5,gsq=2,ff=2,gt=3,gb-,bnh=8,hs-,fxp-,mgt-,ntms=3,hpvp=4,xj-,nxm=3,hsr=7,dcs-,nnx-,gbvzq-,lnhp=6,sm=4,drl=6,dcj=1,xbh-,lthlq-,zvl=7,hj=9,gvf=7,ms-,nnpd=5,tnqhlk-,vfcz=4,kt=1,dcs=2,cnn-,zhdr-,ht-,lm=9,vrb=6,lm-,gbvzq-,hmhs-,kq-,dj=1,kfz=1,fxvg-,ssv-,hqc=9,df=3,ch-,kgb=7,fd-,ml-,zvl=5,mts=5,lg=1,pdm=2,vrb=4,qx-,pjc=1,bdkp=5,dlssls=7,hvk=1,kvj-,tvdl=5,ms-,kfz=2,lthlq=1,cj=7,dbl=3,cgr-,tj=8,vp-,jssb=2,lq=6,xpkljm-,lpmh-,hj-,lz-,kvj-,vtm=3,sxnj-,pk=7,btm=9,rb=1,ms=7,pk-,blf-,hlv-,pdm=7,crr=7,fnbgjj-,dcs=1,xlb-,kl-,lvfd-,kmrzk=8,gzdxh-,lpmh=5,lhqrxp-,kfp-,mfdp=4,hs=6,njzgjp-,fnbgjj-,qx=1,kpns-,lrvb=9,fj-,pdm-,kqb-,jffc=2,hlgzpp=8,cls-,pmr-,tqhs-,gb=9,qm=3,zt-,qvhkp=8,fp-,cg-,mn=9,lmlbf=5,xlb-,xnx-,rm=2,slk=5,gcf-,ljvv=5,xc=6,dfl=3,hsr-,rkr-,cgngq-,nh-,mtbflg-,sr=3,gjbm=6,xc=9,fxp=7,kd-,jjcpm=1,grchdx=4,nktx=9,ksf-,rkkd=5,rg=2,btlt=2,dzd=9,gsdvk=4,vcgxs=8,ngx-,rxsj-,tmvns=1,dc-,tp-,qpcjt=9,fr=2,hmhs=5,tgh-,xv=5,jt=4,tqb-,tp=4,fzt-,blf=4,ljvv-,rrg=3,fm-,xqx-,psb-,fr=3,nzp=6,zkl=2,thxnd=3,djdd-,ktd-,tmn=2,vzf=7,tp=7,zxr=6,lmktdb=9,kvbq=9,rjqxh-,xvnr-,hfnk=8,pgltk=9,pzjs-,hgh-,zhx=3,nxm=5,dcs=8,tsj-,vcgxs-,ssv=6,kgr=2,dvjdr=8,tzh-,slk-,vfk-,jlp=2,nbxlm-,pv-,rbjmn-,tx-,jjcpm-,tmvns-,lcqz=3,nnx=5,dj=7,kgb-,jznz=8,phfgr-,hg=9,xtg-,rl-,dj-,fd=6,ts-,cls-,nc-,pn=9,lc-,blf-,hzqh=2,xnx-,fzt-,ktd-,thq-,scb-,fhpnc=9,pf=2,xc=2,cnn-,pgckd-,bbng-,vrhb=3,rg=2,nh-,tvdl-,zf-,szp-,rbjmn-,xl-,gmn=6,gjbm-,bl-,drt-,fhpnc=1,mdlz=4,tkfcrj=4,fhzbjq=2,fbh-,ks=8,kpnltb=2,ngx-,gp=3,fpfzc=6,sxnj-,gsdvk=4,gc-,tnm-,hfn=8,kpns-,qsg-,fn-,jf=1,vr=3,pxzc-,lql-,zhdr-,vfcz-,dm-,lvfd-,tzh=1,xvmb-,lcqz=5,lp-,gtt-,nbp=4,vq=8,gjhz=3,ff=2,nbq-,jlbm=6,kqb-,cxfh=5,tmn-,qsg-,mfdp=5,nh=8,kc-,bts-,xj-,cgr-,rv=7,lcqz=9,lc-,tgh-,zd-,rxsj=8,tvf=8,rb=4,dqzdbx=4,rtxt-,thxnd=2,dshp=2,hcvsn=7,xl=6,gt=4,nzr-,hnd-,pzjs-,ts=3,kfz-,bbng=6,fm-,nk=2,sqvq-,mtbflg=1,nktx=1,rtxt-,jtm-,dm-,kvj=9,ccfj-,qrd=5,kvbq-,tbvx=6,vl-,rhn-,jvx=1,lm=9,mn=6,pvht=5,sp-,bkj-,fpfzc=2,bdkp-,cbkk=6,sp=2,gjbm-,gzt=9,nkd-,hf=6,jzs=9,lq=3,qx-,rxcv=6,gvtcn-,npm-,jj-,ckzq=7,qjngd=1,kg-,lzhv=3,qd=9,bpv-,pjc-,rkr=9,cgr-,tsj=2,tqhs-,gp=8,bkg=2,mxm-,qjngd-,qt-,fhpnc=4,qxrlr-,szp-,mdlz=6,rp-,xgd=7,jffc-,gr-,nth-,fs-,nqr-,jsdb-,vcgxs-,rhn-,xdqs-,dcs-,mqc-,ckzq=7,vrhb-,hch-,bqq-,fj-,hm=6,nxm=1,vv=9,hpvp-,gtt=1,cj=5,mp=6,mmgq=7,fq=7,fphd=4,fnxn=4,bsp-,gzt-,kl-,kj-,jjcpm-,mqc=8,lhqrxp=8,gq-,xv=4,mgf-,hlv=3,dc=4,vmrr-,hx=2,vz-,sjg=9,vthzt-,mlnd=9,cj-,ht-,hfn=2,xbh-,dcj-,kfp-,nx-,cq-,th=5,kfz-,ccfj-,cztdj=3,bfdbb-,lms=1,btlt-,hx-,bzkc=3,jmnh=1,pk=6,ts=7,xtg=9,tf=1,hqln-,gq=9,zsckf-,gbvzq=2,fljt=5,vcjdc=8,zmql=8,jvg-,chs-,bzc=8,hgc=1,fmbv-,ll-,pn=6,tt-,tcr=2,vtm=9,kqb-,hvqmc-,vv=8,gtt-,mlfj=8,sqvq=4,rmc-,vz-,qxrlr=4,kpg-,rxcv-,fxvg=3,vv-,ksd-,ztv-,sr=5,bts=8,tvdl=5,jqs-,lnhp-,vfcz=7,blf-,gzt-,xzf=1,pdm=5,bkd-,cx=7,kfp-,jssb=3,ft-,gs=6,hrq-,ssmm-,bkg=7,dvl=1,hf-,rb-,thq-,nbp=6,lzhv-,xj-,zzz-,bnh=2,fp=1,tnm-,mx-,mp-,vp-,jtm=3,zxr=3,jjcpm-,sjg-,hb=8,szp-,qdx-,zdnr-,hzqh-,lmmc-,vmrr=2,ksf=4,dp-,rg=4,nj-,cnn-,dcs-,zlg=3,ff-,pgltk=2,hgc=1,vql=9,bljv=1,tcr-,jvx-,sjg-,bnvb=7,jt=4,vr-,rxcfx=1,tt-,vcjdc-,fgdh-,vrb=7,gsq=1,nmv-,cxfh-,rdq=6,fc-,zhx=1,hrq-,fq=2,kvbq-,jgzst=8,btm-,hqc-,lzhv=9,hvxdf-,fk=9,tsj-,dbl=7,rz-,nln=1,zzkc-,pds-,gb=9,tmb=1,fp-,ncvj-,fnbgjj-,ppk-,ghqj-,zt=5,tvf-,cx=8,rz=9,qd-,lg=6,jg=9,pjv-,tvf-,dn=6,jznz-,tgh=8,cbkk-,mqc=4,zkl-,jzs-,mp-,ztd-,hm=3,pjc-,kpnltb-,kpnltb-,fk=4,nj-,qpcjt-,ccm-,thq-,vbbdk-,tmvns-,jznz=4,rsps=1,drt=7,hf=3,drt-,jssb-,mt=6,kj-,nzp=9,hg-,rhn-,pk-,mmgq-,dfl-,fphd-,xqx=4,zlsd=2,dv=6,nth=5,jtm-,qpcjt-,ngx-,xzf=5,lc-,ncvj=2,btm=4,jc=3,dcs=1,njzgjp-,cplm-,bdkp=6,df=1,pjc-,mfs-,hcvsn-,pdd=6,vbbdk-,cg-,bbng-,sdk-,mpp-,cplm=4,gmn-,sz=3,cgrv-,tkk=7,lrvb=8,pv=1,qjngd=1,dvjdr=7,hpvp=3,zsckf=8,ks-,fnxn-,npr-,fq-,hzr-,lm-,nj=5,rxp=4,rkkd-,hfnk-,btm=2,cq-,hvqmc-,kx=2,rv=7,hpvp-,sp=6,jlp-,hm=9,qr-,clnxp=3,ptxfn-,ddbxf-,qf=2,ksd-,lpsr-,kt=5,lpmh=7,tzh-,dvl=9,rz-,dj-,rhn=4,bkg-,kxmlkn-,lhqrxp=8,grfv=5,nbq-,pk-,tmn-,dm=1,szp=2,pf=1,jssb-,xdv-,vvgx-,hfn-,nvj-,tgh-,jznz=3,ngx-,gm=5,bl=5,mt=1,bljv-,db-,nqn-,bg=3,tvf=8,thl-,xpkljm=6,nl=1,tgh=8,mgf=5,bkj-,nvj=4,hgh=9,ggsx-,qf-,lqrlg-,smh-,bq=7,nzq-,qqjc=1,nzp=6,nth-,fz=4,lrvb-,zzz-,dvq=2,phfgr-,xqx-,bv-,bzc=6,kpns=1,hqc-,bkj=9,rbjmn=9,hlgzpp=1,rv=6,zsvhrh-,kc-,szp=9,nnpd-,mfdp=7,szp-,cnn-,bhm-,lqrlg=9,vfcz=4,nln-,ztv=7,hghph-,rv=4,gbvzq-,ngx-,ljvv=5,ckzq-,vvgx=7,lff-,xlb=9,tkk-,cplm=3,hlv-,kd-,ksf=4,vrq=5,pr-,pk-,hgc=5,cv-,jvx=5,hs=8,cgngq-,tkk-,gr=5,hvxdf=6,vd-,hvqmc-,npm-,lrvb=5,tfmq-,pdd-,xpkljm=4,nzp=6,kvj=2,hcvsn=1,qm-,rjj-,rjqxh-,mfdp-,zsckf-,xvnr=3,jjhtxb-,vfcz-,zlg-,tj=4,jxb-,fgdh=1,blf=5,tp-,sjg-,rtxt-,jqrb-,vrb-,mcx-,zdnr-,jlbm-,zxr=8,mts=5,xv=7,npr=2,ngx=1,vd-,pds=8,cls-,zhx=5,bzkc=1,tcr-,dvjdr=8,qtm=2,zxr-,zsckf-,kqb-,hx-,rfkbqp-,gc=7,vt=5,jg=4,fgdh=4,fcb=8,qdq=2,mlnd-,vql-,ppk-,bzkc-,gr=6,nc-,vl-,gccsrh-,dbl=8,gt-,dshp=1,dn-,kfz=1,hlgzpp=3,vthzt-,ptxfn=8,hm=4,kx-,ks=4,fnbgjj-,bcr=7,gvtcn=2,hsbtx=1,ngx-,ccfj=8,thl-,kd=7,rdq-,nhb=8,cgrv-,nx=9,gq=3,nxm=6,npr-,tqb-,gjhz-,cbkk-,gbk=2,dv=9,tbvx-,sz=5,bbng=2,zl=9,qqjc=5,xzf=6,xv-,cq=8,bts=6,grfv=8,bqq=9,gcf=1,jg-,nl=8,dfl-,fxvg=7,nc=2,lv-,vt=8,djdd-,kx-,dbl-,fjqc=6,nlg-,rxsj=3,gbk-,jjcpm=4,pf-,kpg-,nktx=3,gm-,jfx-,gzt-,cgngq-,zx-,fhzbjq=4,jmnh-,ds=7,hg-,xj=9,thxnd=2,pn-,btm-,tmvns-,nnx-,jqrb-,lv=8,nq=8,ts-,nnpd=8,jpj-,kq=9,pdm=8,ch-,xb=3,fxvg-,kfq-,phfgr=2,gb=8,qsg-,jqs-,grfv=9,qtm-,rvq-,pzjs-,jfx=6,kvbq=9,jqfmp=4,jfx-,rxcv-,bts=2,nvj-,qdq=1,rhn=6,mqc-,kv-,tvzv=9,pdm=7,xpkljm-,kgb-,ckzq-,kn-,xr=3,pp=2,gs-,pdd=7,gp-,dn=2,nj-,pdm-,mgf-,xdv=8,fc=4,psb-,ts-,xpkljm=1,bsp-,lzhv-,xc-,pmr=5,dm=3,xhn=4,jjcpm-,hv=2,hcgd=8,nzr=7,zmg=6,zvl=1,ds-,tvf-,fnhpf=1,gccsrh-,xr=7,fgdh=9,phfgr=7,thq=7,nbp=2,hs=2,jjhtxb-,nzp-,fnhpf=6,fhpnc-,hvxdf=9,dm=8,rz=6,dshp-,kvj=6,jjhtxb=9,fs-,fj-,ff-,mdlz-,mqc=7,lc-,vz=4,lff-,hrq-,rhv=4,lps=1,tsj=1,pdm=6,zmg=6,bv=1,vthzt-,mx=3,lzhv-,bzkc=8,gjbm=6,chs-,rkr=3,fn=5,rdq=1,pgltk=1,dvn-,nq-,cf=5,dvg-,rtxt-,cgr=2,ljvv=5,qd=9,vvgx=9,ghqj=4,xgd=3,mts-,zsckf=5,rsps=3,rlsl-,xvmb-,qd-,pdd-,btlt=7,bg-,nvj=4,lps-,zzz=8,lqrlg=5,cf-,btlt-,mt-,hzr-,vq=4,xc-,hvqmc-,jj-,gjhz-,xc-,kl=3,jvg=7,nhb-,tvf=2,kfq=9,drt-,zmg-,qnhgvl=8,vcjdc-,kd=1,pp=3,rm=5,jpj-,xl-,jgzst=8,fbh-,kqb-,fp=6,pvht-,cnn=6,fnxn-,msm-,mp-,xzf-,pvpn-,nqk-,bsp=4,jf-,kfz-,zvl-,sgs-,fm=2,slk=3,hggm-,bzkc-,pdm-,rxcfx=3,nnx=2,gzt=2,hzqh=7,fxp-,fzt=1,gt-,lmlbf=4,xl=6,bts=9,vx=6,hldlq=8,bts-,zhdr=9,zlsd-,vv-,pmr=6,ckzq-,rs-,jtm=8,ccm=7,tg=4,jvx-,tkk=8,gvtcn-,dcj=5,lzhv-,hghph=4,rm=1,fnbgjj=4,zzz=2,ccm-,cv=5,clb-,cxfh-,qngk=6,fk=5,kqb-,mgt=6,fhpnc-,ll=4,fzt=3,qncs-,clnxp-,jffc=5,kfp-,fxvg=2,bsp=9,bjn-,zsvhrh=8,qngk=5,hpvp-,lms=7,jffc=2,xzf-,bbng-,drt=3,mlfj-,xjp=9,cgngq=7,tnm-,kgb=8,mxm-,rp-,hf-,dvg-,vx=6,cx-,mdcjcv-,pmr=1,qx-,hf-,tmb-,lzhv=2,ddbxf-,hggm-,gcf-,rxcfx=8,kc=7,pgckd-,rmc=2,xbh-,hm-,lhqrxp-,lff-,rxcfx=5,fnhpf=3,zhx=5,cg-,kd=2,hzqh=3,jgkzf-,dshp=4,jjcpm=7,nlg=5,bl=7,scb=5,dv=2,kq-,nvj-,hq-,tmn-,xgd-,tf=3,dv=6,sjg=2,lms=8,zdnr=9,gm=6,mcx-,gzt-,kmrzk-,hsr-,vv=4,qjngd=5,kj=2,qngk=3,vthzt-,hggm-,mfnm=9,jssb-,nkd-,tnkv-,xvnr-,gjbm-,tp-,pvpn=7,cls-,szp-,qnh=4,dlssls=8,ptxfn=5,xb=4,gzt-,nnx-,xr=2,vql=2,cxfh-,rp=5,fz=5,bs=2,tqb=4,fljt=7,tp=7,kn=2,zd=4,cgr-,jqrb=4,hq=7,kc-,fnbgjj-,jlbm-,cg=4,lpsr=1,hsbtx=1,cl-,thl-,vd=7,hsr-,rkr-,pzjs-,dvjdr=9,tvf=9,jg-,nln=7,ccfj-,jqrb=5,zzz-,dm-,bkj=9,hv-,lthlq-,bnvb-,zsckf=4,tmb=4,xlb=8,cg=5,lz=3,jh=9,smh-,xpkljm-,nzq-,cls=6,tnqhlk=4,bkj=8,pmr-,dcs-,ddbxf=6,vtm-,jc=6,xvmb=2,gmn=4,jffc-,pgckd=8,crr-,fnxn=5,gvtcn-,rgl=4,bsp-,vthzt=6,tfmq=3,mdlz-,sz=5,qnhgvl-,jfx-,rhn=2,ztd-,bdkp=5,zsvhrh=4,pmr-,jlbm=6,thq=6,dvl=6,xzf-,xdqs=9,ppk=6,sp-,lzls-,gbvzq-,jqrb=5,vfk-,hq-,lrvb=8,cg-,dvq=4,rfkbqp=3,ppk-,fnbgjj-,vdgn-,qt=6,vrcrz=6,rb-,zx-,bts-,bcr=4,zkx=6,qdx-,nktx=9,xttmp-,jfx-,ms-,zkx=3,zjhsg=3,fj=2,kq-,gq=6,vrb-,vcgxs-,fp=2,knb-,tf=1,pr-,gc=3,gmn-,jqrb-,nbq-,rdq=8,mfnm=6,vl-,srl-,lcqz=4,qxrlr-,qr-,rb-,btm-,vdgn-,bnvb=5,lms-,hch-,zmg-,glrql=7,npr-,tvdl=3,qnh=2,mx-,fbh-,srp-,grchdx-,zlg=1,mqc=1,zjhsg-,qtm=6,bzc-,gq=2,cgrv-,rb=8,pnzs=1,kt=3,fxp-,gt-,pn=7,rxcv=4,jtm=8,sr-,xlb=3,dvn-,fs=8,mn=3,zhdr-,cgngq-,fbh-,sqvq-,zzkc=2,drt=8,hcvsn=9,tvzv=9,dn=5,jg-,nnpd-,rxp=1,hv-,bg-,mgt=6,zx-,rtxt=7,bkj=1,kq=6,lff-,xhn-,qx-,dv-,pr-,lp-,rdq=3,mcx=7,zl-,zf-,nk- diff --git a/src/day15.rs b/src/day15.rs new file mode 100644 index 0000000..f5d8bc8 --- /dev/null +++ b/src/day15.rs @@ -0,0 +1,55 @@ +fn hash(s: &str) -> u8 { + let mut value = 0; + for c in s.chars() { + value += c as usize; + value *= 17; + value %= 256; + } + value as u8 +} + +fn sum_hashes<'a>(s: impl std::iter::Iterator) -> usize { + let mut sum: usize = 0; + for step in s { + sum += hash(step) as usize; + } + sum +} + +pub fn main() { + match std::fs::read_to_string("day15.input") { + Ok(input) => { + let sum = sum_hashes(input.trim_end().split(',')); + println!("sum of HASHes = {}", sum); + }, + Err(reason) => println!("error = {}", reason), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_hash() { + assert_eq!(hash("HASH"), 52u8); + + assert_eq!(hash("rn=1"), 30); + assert_eq!(hash("cm-"), 253); + assert_eq!(hash("qp=3"), 97); + assert_eq!(hash("cm=2"), 47); + assert_eq!(hash("qp-"), 14); + assert_eq!(hash("pc=4"), 180); + assert_eq!(hash("ot=9"), 9); + assert_eq!(hash("ab=5"), 197); + assert_eq!(hash("pc-"), 48); + assert_eq!(hash("pc=6"), 214); + assert_eq!(hash("ot=7"), 231); + } + + #[test] + fn test_part1() { + let input = "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"; + assert_eq!(sum_hashes(input.split(',')), 1320); + } +} diff --git a/src/main.rs b/src/main.rs index 083b0fa..2dd5e23 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day14; +mod day15; fn main() { - day14::main() + day15::main() } From b176d28eb6eafb653d8cedee4df5754cb3a7a342 Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Wed, 20 Dec 2023 12:56:31 +0100 Subject: [PATCH 118/120] Day 15, part 2: HASHMAP --- src/day15.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/src/day15.rs b/src/day15.rs index f5d8bc8..8fc5e77 100644 --- a/src/day15.rs +++ b/src/day15.rs @@ -8,6 +8,41 @@ fn hash(s: &str) -> u8 { value as u8 } +struct HashMap { + boxes: Vec>, +} + +impl HashMap { + pub fn new() -> HashMap { + HashMap { + boxes: vec![Vec::new(); 256], + } + } + + pub fn put(&mut self, key: &str, value: u8) { + let hash = hash(key); + let bucket = &mut self.boxes[hash as usize]; + for (k, v) in bucket.iter_mut() { + if *k == key { + *v = value; + return; + } + } + bucket.push((key.to_string(), value)); + } + + pub fn del(&mut self, key: &str) { + let hash = hash(key); + let bucket = &mut self.boxes[hash as usize]; + for i in 0..bucket.len() { + if bucket[i].0 == key { + bucket.remove(i); + return; + } + } + } +} + fn sum_hashes<'a>(s: impl std::iter::Iterator) -> usize { let mut sum: usize = 0; for step in s { @@ -16,11 +51,49 @@ fn sum_hashes<'a>(s: impl std::iter::Iterator) -> usize { sum } +fn run_initialization_steps<'a>(s: impl std::iter::Iterator, print: bool) -> usize { + let mut map = HashMap::new(); + + // Load the lenses into the boxes + for step in s { + if let Some((key, value)) = step.split_once('=') { + map.put(key, value.parse().unwrap()); + } else if let Some(key) = step.strip_suffix('-') { + map.del(key); + } else { + panic!("unexpected input"); + } + } + + // Calculate the focusing power + let mut power = 0; + for (i, b) in map.boxes.iter().enumerate() { + if b.is_empty() { + continue; + } + if print { + print!("Box {}:", i); + } + for (slot, (key, value)) in b.iter().enumerate() { + if print { + print!(" [{} {}]", key, value); + } + power += (i + 1) * (slot + 1) * *value as usize; + } + if print { + println!(); + } + } + power +} + pub fn main() { match std::fs::read_to_string("day15.input") { Ok(input) => { let sum = sum_hashes(input.trim_end().split(',')); println!("sum of HASHes = {}", sum); + let focusing_power = run_initialization_steps(input.trim_end().split(','), true); + println!("focusing power = {}", focusing_power); }, Err(reason) => println!("error = {}", reason), } @@ -30,6 +103,8 @@ pub fn main() { mod tests { use super::*; + static INPUT: &str = "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"; + #[test] fn test_hash() { assert_eq!(hash("HASH"), 52u8); @@ -49,7 +124,11 @@ mod tests { #[test] fn test_part1() { - let input = "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"; - assert_eq!(sum_hashes(input.split(',')), 1320); + assert_eq!(sum_hashes(INPUT.split(',')), 1320); + } + + #[test] + fn test_part2() { + assert_eq!(run_initialization_steps(INPUT.split(','), true), 145); } } From 8d06f9b8ec489a71b7b9949556ed39a439a3a4ab Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Wed, 20 Dec 2023 14:01:45 +0100 Subject: [PATCH 119/120] Day 16, part 1: This feels somewhat familiar... --- day16.input | 110 ++++++++++++++++++++++++ src/day16.rs | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 +- 3 files changed, 342 insertions(+), 2 deletions(-) create mode 100644 day16.input create mode 100644 src/day16.rs diff --git a/day16.input b/day16.input new file mode 100644 index 0000000..00686c8 --- /dev/null +++ b/day16.input @@ -0,0 +1,110 @@ +\.-/...-\......../.|......|.........../..-..................|....-.\............................../........... +..........-.............\...\.........|..\.......................-..........-.......\.../.......-/............ +........|.............-.....|..|........................\.\.../../.....-........................\............. +....../\.....................|........|.....-...........-..\......./-.............................-........./. +.\..\.............-........|.......|...|..............................-..-......-......|...................... +..........|/...\.............\............../-......\.../........................./............./.../......../ +..............\......./..-...............|...........\...|............|...........-..-............|........... +..........-...............|..././...........................................|...........-.../.-.|.....|....... +.........-...|..................-...........\.-...................../.../........................|/......./... +.................................-.././...................|\..............|.........../....................... +.............../......-.................\....--.....-............................./.|./.................|..... +..../....|...|..................../....\...|............|...../.././../--......\.\....|.......-............\./ +......\....-...|......\...........-......./..................../.....-..............\.............|......./... +............|.\...................|.........................|........\............................./.\.......| +............../...............................|.........../.................\-.................../........../. +.|....|...........|..................|......./|\\.|\.-...\..../.........//........|............../...........| +........................|.....--......|.............-..................\...../..../.......-....|...\.......... +...............\........-........../...-|............\......./.\...........-|................/.-.............. +..../....|.\.............|......|...............................................|.................\........... +.\...\......./.....|.\....|..................-../|-......................|.................-..|......\........ +.../.........................................\.....././....................|.......-........-......\....|..... +.................\./\..-../......../...\................................-......-..\........................... +.......--..-........\/........./........../...............\..............\...-........-......-../.........|... +.|...............-........./..............\..\......................|......./..|..............-.......|.|..... +........./............\............|........\...|...\........-.......................|...................\.... +..................-\......../.................\.......\.....|...........|..|-........\.............|.......\\. +...|.........../.......|...../...|...\........\\...................................-............-../...../.... +......./....................|.........../...-................-....................\.......|................... +\....\.......................-.|.\...../..-...................|......................-..................../... +......|........-|...-/.|........................./.....|.....\.........-........-......-.............././..... +......|.............-.\...............................\..|....\..............|./..|./...\......./..........|\| +......././.\...................-...-............/...................|/..........-\./.................|........ +.........|..........|\../.........\..............-.........\................../\./.............-.............. +...\.......................\..................................\...........................................|... +...|........\..........|....|..../..|.........-\.................-...-..\.\.........\............|....|...//.. +.././.....|.....-..........|.................\.........\........./......-...-.\.\.....................\....... +......./....\........\\..\...|...../.................|.......|.\.....\............................../\....\... +.........\......../.\............|...............................................................|/........... +.\.....-\-.........|.........|....|...........-....\.....|................\...............-............./..... +.....-..............................-.....-..........-..................../..../........................|..... +...........\...........-/....................-.....-............/........|........-/.........--./........-..\\ +.|................................................|..................-.......|.............|\/................ +.|.................-.-..........|.........................../..../....../.....\...../......./................. +........./..../..|..........\..................\....................................................../....... +.........\............|.../......../........|......................../..../...|.\...\......................|.. +........./................\.............\........|....................\./......|.........-....../...../....... +..../.....|...../........-...................|............/.....||...............-....-.-..................... +\./...\.|...|.............|.......\....../|...\\/.|.../....-.........\\|..|....-........\............-.......| +......\-..............|.....\.....|...\..............................|.....................\......-.....|..... +......\.-..........-..|......................................-..../......................../........\.......|. +/...................-...\.........--.............................\...........\................|......./....... +.................-......-..../..\.............-./|......-....\...........-...................\.....|........-. +|........--.............\...-....|.......|.\............|...../\...........\/../............................-. +...|./-..\.|...........\........../..............................\......-.......-.....|..........-........./.. +.......-|..................-..........|..-............................../.............|..|.||................. +....-......................\....\..................\......./............./..-........|..............-....|.... +-..........-.........-.../|........--.............-................|..../|.................|.................. +...\......./..\..\......./|.....|-.............-............................\..\......\...-..\...............\ +./......................|..........\...........|.|.......\..........\......................................\.. +................|...............-.../....\......./.\........-..............................|...-....-......... +..\.......................\..../..|.-.........-.............\.......|../.|.|..|........|..............-....... +...........\................\..........................\.....................\........|....................... +..........|....\.......\...........|...../......................................./...\.../........../......... +./...............\...........|..-....-./..\...\...\../...............-\............\....\............-........ +././............|................|........../...\...../.............-....-.............\...................... +....-.|..................../.............................-...............................|.................... +..-......|....-.........-...\......\.........||....-.\............................-...|..............|........ +........\...........\.-.......\.../.........\.../.....|.................../..|..|....\..../..-................ +..........-..................\..|...|.|..\......................./...........-......./.............|..\...../. +.\......|\.|..\.......|\.-.......-........../........../..........\.........../.........|..................... +./..........|..................//.|......|........-...\...//............-.../..............|.......-....-..... +...............\......\........|.-................\......-...................|.............-............-.-... +...........................\/...........\../..\....................\...........|.............-..........-..... +.............../........\|.........\..........-......../............-..........|........|/.................... +....\................-..................././........|.....|...........................-..|.................... +\-............-.......\......\.................../.......-.../............/....-..\.......|................|.. +.........................../....../.|...\/...\........-|.|.......\..-........-............................../. +.................\.....................|..........|.............|......|/.\..........................-........ +....\../................................|.......-......|.................-......................|...-.../..... +....-.........|..../|..............................-|...............................-..-......\.....-......... +./\...............|.|..............-./..|........./...................................................\....... +..............-....\..|....../.....\.............\..............................-...-..../.....|.............. +........-.........|..............................................-....\--...........|\...................../.. +................/.|.................-....|......./............-...................../.-./\................|... +................|............................../..-./.....|..-........................./.....|..............-. +....../........../.......|...|.....\........./.............|..................................|.|............. +....................................................||.....|................/......-....../....../............ +.........../.....\...................|...........\../....................................../.............../.. +./.|............../.............................\..|....\-............./...................................... +.........\................../-.....|...........\................|...../..................................|.... +..|...../.....|...............\.....-.................................|/............-..|..-...|......-........ +....|....-..............|.......|............./\-...........\//.........|...........\...../..............--... +.............-........\|...........................-....../....||............/......./....................../. +|..................-......\.........-.......|..............................\.|/..................\......\.-... +....../.......................|........|..|.\...........|.........\................\\..................\.../.. +...........-....|...........||...-.......|.|....-.....\\-................|.........../..................\/.... +................|.-.................|-./..-..|.........-..............-.........-../........................-. +.....................-.....................................|.........\......||./................|............. +............/...-............|......./......................................../..........................-.... +..../.......\.-............|..........|....-...........\.-.................................\./...|............ +...........|.-........|.|....-...........\......-...-..........|.\.|.|.....\....\............../.............. +......\...\....../....\......\.|......................./.......................\.................../..../\.... +...../.|...............|.../\.........................................-...........|./........................| +.........................-.-.......\./..........|.........|/.......-......................-...-..|\|........\. +..................|......-..................|..........\..-../........................-......\...\............ +..|...............\.............../.........-./............../.../..../.|\......\..../-.....|....-.........|.. +...-..-..............--...|...................................................|.-.../.../.....\.....\......... +.\./.../..............././.........\.........|..\..........\.................\..|.....-......-................ +......-...................|../....................|...............|.............|/..\.......|........\......|. +......\/.....|................./..................................|.......|./........|.............-...-...... diff --git a/src/day16.rs b/src/day16.rs new file mode 100644 index 0000000..9480eee --- /dev/null +++ b/src/day16.rs @@ -0,0 +1,230 @@ +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Tile { + Empty = '.' as isize, + SplitHorizontal = '-' as isize, + SplitVertical = '|' as isize, + MirrorBottomTop = '/' as isize, + MirrorTopBottom = '\\' as isize, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Direction { + Up, + Down, + Left, + Right, +} + +struct Contraption { + tiles: Vec>, +} + +impl std::str::FromStr for Contraption { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let mut tiles = Vec::new(); + for line in s.lines() { + let mut row = Vec::new(); + for c in line.chars() { + row.push(match c { + '.' => Tile::Empty, + '-' => Tile::SplitHorizontal, + '|' => Tile::SplitVertical, + '/' => Tile::MirrorBottomTop, + '\\' => Tile::MirrorTopBottom, + _ => return Err("invalid character"), + }); + } + tiles.push(row); + } + Ok(Contraption { tiles }) + } +} + +impl Contraption { + pub fn simulate_light_beam(&self, print: bool, stop_after: Option) -> usize { + let mut beam_heads: Vec<(usize, usize, Direction)> = vec![]; + + // Create a field of the same size as the contraption and track the direction of each beam + // that hit that tile. + let mut field: Vec>> = self.tiles.iter() + .map(|row| { + vec![0; row.len()].iter() + .map(|_| vec![]) + .collect() + }).collect(); + + // Start with one beam in the top left corner, pointing right: + let mut steps = 0; + beam_heads.push((0, 0, Direction::Right)); + while let Some((x, y, direction)) = beam_heads.pop() { + if print { + println!("beam at ({}, {}) {:?}", x, y, direction); + } + // Add the direction of that beam to the field IFF it didn't exist yet. + // If it did, we will certainly not produce anything new, and can drop this beam. + if field[y][x].contains(&direction) { + if print { + println!("beam already hit this tile"); + } + continue; + } + field[y][x].push(direction); + + if print { + self.print_field(&field); + } + + // Evaluate the tile itself + let mut new_beams = vec![]; + match self.tiles[y][x] { + Tile::Empty => { + // Nothing happens, the beam continues in its direction. + new_beams.push(self.move_beam((x, y, direction))); + }, + Tile::MirrorBottomTop => { + // The beam changes direction. + new_beams.push(self.move_beam((x, y, match direction { + Direction::Up => Direction::Right, + Direction::Down => Direction::Left, + Direction::Left => Direction::Down, + Direction::Right => Direction::Up, + }))); + }, + Tile::MirrorTopBottom => { + // The beam changes direction. + new_beams.push(self.move_beam((x, y, match direction { + Direction::Up => Direction::Left, + Direction::Down => Direction::Right, + Direction::Left => Direction::Up, + Direction::Right => Direction::Down, + }))); + }, + Tile::SplitHorizontal => { + // If the beam is currently vertical it splits into two beams, one going left and one going right, + // otherwise it passes through. + if direction == Direction::Up || direction == Direction::Down { + new_beams.push(self.move_beam((x, y, Direction::Left))); + new_beams.push(self.move_beam((x, y, Direction::Right))); + } else { + new_beams.push(self.move_beam((x, y, direction))); + } + }, + Tile::SplitVertical => { + // If the beam is currently horizontal it splits into two beams, one going up and one going down, + // otherwise it passes through. + if direction == Direction::Left || direction == Direction::Right { + new_beams.push(self.move_beam((x, y, Direction::Up))); + new_beams.push(self.move_beam((x, y, Direction::Down))); + } else { + new_beams.push(self.move_beam((x, y, direction))); + } + }, + } + + new_beams.drain(..) + .filter_map(|b| { + if b.is_some() { + if print { + println!("new beam {:?}", b); + } + b + } else { + if print { + println!("beam lost") + } + None + } + }) + .for_each(|b| beam_heads.push(b)); + + if print { + println!("active beams = {}", beam_heads.len()); + } + + steps += 1; + if let Some(stop_after) = stop_after { + if stop_after == steps { + break; + } + } + } + + // Sum up all energized tiles, ignoring how many beams touched a single tile. + field.iter().map(|row| row.iter().map(|directions| if directions.is_empty() { 0 } else { 1 }).sum::()).sum::() + } + + fn move_beam(&self, beam: (usize, usize, Direction)) -> Option<(usize, usize, Direction)> { + let (x, y, direction) = beam; + match direction { + Direction::Up => if (y as isize) - 1 < 0 { None } else { Some((x, y - 1, direction)) }, + Direction::Down => if y + 1 >= self.tiles.len() { None } else { Some((x, y + 1, direction)) }, + Direction::Left => if (x as isize) - 1 < 0 { None } else { Some((x - 1, y, direction)) }, + Direction::Right => if x + 1 >= self.tiles[0].len() { None } else { Some((x + 1, y, direction)) }, + } + } + + fn print_field(&self, field: &[Vec>]) { + // Clear screen and move to top left corner + print!("{esc}[2J{esc}[1;1H", esc = 27 as char); + + for (y, row) in field.iter().enumerate() { + for (x, directions) in row.iter().enumerate() { + print!("{}", match self.tiles[y][x] { + Tile::Empty => { + match directions.len() { + 0 => '.', + 1 => match directions[0] { + Direction::Up => '^', + Direction::Down => 'v', + Direction::Left => '<', + Direction::Right => '>', + }, + _ => 'X', + } + }, + Tile::SplitHorizontal => '-', + Tile::SplitVertical => '|', + Tile::MirrorBottomTop => '/', + Tile::MirrorTopBottom => '\\', + }); + } + println!(); + } + } +} + +pub fn main() { + match std::fs::read_to_string("day16.input") { + Ok(input) => { + if let Ok(contraption) = input.parse::() { + println!("part1 = {}", contraption.simulate_light_beam(true, None)); + } else { + println!("error parsing input"); + } + }, + Err(reason) => println!("error = {}", reason), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + static EXAMPLE: &str = ".|...\\.... +|.-.\\..... +.....|-... +........|. +.......... +.........\\ +..../.\\\\.. +.-.-/..|.. +.|....-|.\\ +..//.|...."; + + #[test] + fn part1() { + assert_eq!(EXAMPLE.parse::().unwrap().simulate_light_beam(true, Some(200)), 46); + } +} diff --git a/src/main.rs b/src/main.rs index 2dd5e23..c6bf939 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod day15; +mod day16; fn main() { - day15::main() + day16::main() } From e254be31ad43a296133592bc7f3b19fcf629dc5a Mon Sep 17 00:00:00 2001 From: "Andreas Kohn (Framer)" Date: Wed, 20 Dec 2023 14:18:29 +0100 Subject: [PATCH 120/120] Day 16, part 2: Easy enough to just do it. --- src/day16.rs | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/src/day16.rs b/src/day16.rs index 9480eee..de48245 100644 --- a/src/day16.rs +++ b/src/day16.rs @@ -43,7 +43,45 @@ impl std::str::FromStr for Contraption { } impl Contraption { - pub fn simulate_light_beam(&self, print: bool, stop_after: Option) -> usize { + pub fn simulate_all_light_beams(&self) -> usize { + let mut result = 0; + let mut best = None; + // Simulate beams coming from left and right + for y in 0..self.tiles.len() { + let mut source = (0, y, Direction::Right); + let mut num = self.simulate_light_beam(source, false, None); + if num > result { + result = num; + best = Some(source); + } + source = (self.tiles[y].len() - 1, y, Direction::Left); + num = self.simulate_light_beam(source, false, None); + if num > result { + result = num; + best = Some(source); + } + } + // Simulate beams coming from top and bottom + for x in 0..self.tiles[0].len() { + let mut source = (x, 0, Direction::Down); + let mut num = self.simulate_light_beam(source, false, None); + if num > result { + result = num; + best = Some(source); + } + source = (x, self.tiles.len() - 1, Direction::Up); + num = self.simulate_light_beam(source, false, None); + if num > result { + result = num; + best = Some(source); + } + } + + println!("best = {:?}", best); + result + } + + pub fn simulate_light_beam(&self, source: (usize, usize, Direction), print: bool, stop_after: Option) -> usize { let mut beam_heads: Vec<(usize, usize, Direction)> = vec![]; // Create a field of the same size as the contraption and track the direction of each beam @@ -57,7 +95,7 @@ impl Contraption { // Start with one beam in the top left corner, pointing right: let mut steps = 0; - beam_heads.push((0, 0, Direction::Right)); + beam_heads.push(source); while let Some((x, y, direction)) = beam_heads.pop() { if print { println!("beam at ({}, {}) {:?}", x, y, direction); @@ -199,7 +237,8 @@ pub fn main() { match std::fs::read_to_string("day16.input") { Ok(input) => { if let Ok(contraption) = input.parse::() { - println!("part1 = {}", contraption.simulate_light_beam(true, None)); + println!("part1 = {}", contraption.simulate_light_beam((0, 0, Direction::Right), false, None)); + println!("part2 = {}", contraption.simulate_all_light_beams()); } else { println!("error parsing input"); } @@ -225,6 +264,6 @@ mod tests { #[test] fn part1() { - assert_eq!(EXAMPLE.parse::().unwrap().simulate_light_beam(true, Some(200)), 46); + assert_eq!(EXAMPLE.parse::().unwrap().simulate_light_beam((0, 0, Direction::Right), true, Some(200)), 46); } } pFad - Phonifier reborn

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

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


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy