commit 90b4b961547ff3b1b78f2872676a8ca686ab0899 Author: Amolith Date: Mon Dec 1 17:38:16 2025 -0700 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..599be4eb9294fa93ae3e22fc8d4e3828b74d8dd2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.beam +*.ez +/build +erl_crash.dump diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000000000000000000000000000000000..7cbe9f07dafd4114f9097400b52150e4304381fe --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,64 @@ +# AGENTS.md + +Guidelines for AI agents working in this Advent of Code repository. + +## Project Overview + +Gleam-based Advent of Code solutions with two parallel implementation tracks (`mine/` and `llm/`) for comparing human vs LLM-generated solutions side-by-side with benchmarking. + +## Commands + +```console +$ gleam build # Compile the project +$ gleam test # Run all tests +$ gleam run # Run all available days with comparison (default) +$ gleam run -- # Run specific day with comparison +$ gleam run -- -e # Run with example input (--example) +$ gleam run -- -n # Run without comparison, mine/ only (--no-compare) +$ gleam run -- 1 -en # Flags can be combined +``` + +## Code Organization + +``` +src/ +├── aoc.gleam # CLI entry point, argument parsing, day dispatch +├── compare.gleam # Benchmarking harness for mine/ vs llm/ comparison +├── utils.gleam # Input file reading utilities +└── internal/ + ├── mine/ # Human-written solutions + └── llm/ # LLM-generated solutions + +input/ +├── dayXX.txt # Real puzzle input +└── dayXX_example.txt # Example input from problem description + +test/ +└── aoc_test.gleam # Tests for both implementations +``` + +## Documentation + +When making changes that affect CLI usage, project structure, or workflows, update the relevant documentation (this file and README.md) to reflect those changes. + +## Adding a New Day + +1. Create `src/internal/mine/dayXX.gleam` with `pub fn part1(input: List(String)) -> Int` and `pub fn part2(input: List(String)) -> Int` and bodies of just `todo`. +2. Create `src/internal/llm/dayXX.gleam` with the same interface. Make sure to include the `//// Authored-by: [Model] via Crush` header that you're told to use for commits. +3. Ask the user to paste the input for `input/dayXX_example.txt`, then download the contents of `https://adventofcode.com/2025/day/XX/input` to `input/dayXX.txt`. +4. Wire up dispatch in `src/aoc.gleam`: + - Add import: `import internal/mine/dayXX as mine_dayXX` + - Add case to `run_parts` +5. Wire up comparison in `src/compare.gleam`: + - Add imports for both implementations + - Add `pub fn dayXX(input: List(String)) -> Nil` function + - Add case to `run_comparison` in aoc.gleam +6. Add the day number to `available_days` in `src/aoc.gleam` +7. Add tests in `test/aoc_test.gleam` + +## Conventions + +- Naming: `mine_dayXX` and `llm_dayXX` for imports to distinguish implementations +- Types: Define custom types for domain concepts (Movement, Rotation, etc.) +- Constants: Use module-level `const` for magic numbers (e.g., `const starting_position = 50`) +- Pipeline style: Heavy use of `|>` operator for data transformation diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e17c17cc3516e0582335192ac501ca879983de7e --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# Advent of Code 2025 (Gleam) + +Includes parallel me- (`mine/`) and LLM- (`llm/`) generated implementations for +side-by-side comparison. I'm using [Crush] and whatever models interest me. Each +LLM-authored file includes a header indicating with model was the primary +author. + +[Crush]: https://git.secluded.site/crush + +## Usage + +```console +$ gleam run # Run all days with comparison (default) +$ gleam run -- # Run specific day with comparison +$ gleam run -- -e # Run all days with example input +$ gleam run -- -n # Run specific day without comparison (mine/ only) +$ gleam run -- -en # Combine flags +``` + +## Results + +```console +❯ gleam run + Compiled in 0.04s + Running aoc.main +=== Day 1 === +Comparing implementations... + +--- Part 1 --- +Mine: XXXX (5.3ms) +LLM: XXXX (18.4ms) +✓ Results match +Mine 3.46x faster + +--- Part 2 --- +Mine: XXXX (2.3ms) +LLM: XXXX (17.3ms) +✓ Results match +Mine 7.50x faster +``` diff --git a/crush.json b/crush.json new file mode 100644 index 0000000000000000000000000000000000000000..3edc0f8c80f732d70f2659fd3d53b8e6c90af564 --- /dev/null +++ b/crush.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://charm.land/crush.json", + "lsp": { + "gleam": { + "command": "gleam", + "args": ["lsp"] + } + }, + "mcp": { + "hexdocs": { + "type": "stdio", + "command": "hexdocs-mcp", + "env": { + "HEXDOCS_MCP_DEFAULT_EMBEDDING_MODEL": "manutic/nomic-embed-code", + "HEXDOCS_MCP_PATH": "$HOME/.config/hexdocs-mcp" + } + } + } +} diff --git a/gleam.toml b/gleam.toml new file mode 100644 index 0000000000000000000000000000000000000000..da8884e421328831e8457e0bec96a6a07c417a5d --- /dev/null +++ b/gleam.toml @@ -0,0 +1,22 @@ +name = "aoc" +version = "1.0.0" + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +# description = "" +# licences = ["Apache-2.0"] +# repository = { type = "github", user = "", repo = "" } +# links = [{ title = "Website", href = "" }] +# +# For a full reference of all the available options, you can have a look at +# https://gleam.run/writing-gleam/gleam-toml/. + +[dependencies] +gleam_stdlib = ">= 0.44.0 and < 2.0.0" +argv = ">= 1.0.2 and < 2.0.0" +simplifile = ">= 2.3.1 and < 3.0.0" +birl = ">= 1.8.0 and < 2.0.0" + +[dev-dependencies] +gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/input/day01.txt b/input/day01.txt new file mode 100644 index 0000000000000000000000000000000000000000..d914b2eb1e87caf8186670975c04f490350387ee --- /dev/null +++ b/input/day01.txt @@ -0,0 +1,4147 @@ +R41 +L10 +L18 +R22 +R17 +L29 +R4 +R32 +L32 +R19 +L29 +L13 +R25 +L11 +R47 +L10 +L12 +L29 +R8 +L32 +L38 +L27 +L4 +L34 +R19 +R23 +L49 +R25 +R49 +R13 +L7 +R17 +R23 +R10 +L43 +R45 +L16 +R49 +R7 +R17 +L7 +L44 +R35 +L27 +R16 +L26 +L48 +R4 +R27 +L49 +R95 +R18 +L13 +L97 +R64 +R33 +L68 +L86 +R95 +L41 +L12 +L96 +R10 +R30 +L59 +L1 +L62 +R76 +R33 +R81 +L16 +R67 +L51 +L89 +R86 +R52 +R84 +R64 +L97 +L57 +R65 +R55 +R94 +R32 +L89 +L63 +L89 +L48 +L74 +R74 +R65 +L62 +R97 +L94 +L3 +R24 +L36 +R76 +R33 +L66 +R66 +R65 +R85 +L50 +L11 +L40 +R51 +R49 +R772 +L95 +R674 +L350 +R525 +R25 +L997 +L303 +L75 +R75 +R278 +L12 +R25 +L91 +R391 +L91 +R28 +R72 +R644 +R56 +R37 +L316 +L23 +L98 +L54 +L25 +L92 +R71 +L52 +L24 +L62 +L63 +L99 +R75 +L53 +L822 +R21 +L21 +R72 +L72 +R26 +L26 +R27 +L527 +L60 +R22 +R71 +L33 +L19 +L898 +L50 +L604 +L6 +L766 +R3 +L160 +R673 +R5 +R22 +L195 +L586 +R81 +R83 +R98 +R864 +L45 +L321 +R21 +L13 +L87 +R83 +R331 +L35 +L73 +L77 +R71 +L15 +L53 +R386 +R82 +L452 +R52 +R6 +L663 +L742 +R70 +R50 +L117 +R18 +R27 +L29 +R80 +L798 +R22 +L24 +L75 +L25 +R78 +L27 +R49 +R797 +R37 +R66 +R1 +L95 +L68 +L38 +R763 +L93 +L61 +R19 +R94 +R69 +R709 +L78 +R5 +R23 +R18 +R57 +L364 +L58 +L993 +R90 +L45 +L55 +L79 +R83 +L211 +R222 +L538 +R21 +R68 +R6 +R77 +R799 +R8 +L56 +R72 +L91 +L84 +R7 +L4 +R632 +R6 +L250 +L697 +L14 +R43 +R80 +R243 +R98 +L43 +R36 +R4 +R62 +R66 +R771 +L39 +L55 +L85 +L65 +L8 +L91 +R51 +L51 +R69 +L7 +R331 +L69 +L95 +L64 +R441 +L739 +R39 +L8 +L18 +L40 +L29 +L3 +L71 +L20 +R289 +L45 +R365 +R54 +L74 +L349 +R34 +L96 +R11 +R50 +R50 +R33 +L533 +L4 +R4 +R14 +L96 +R44 +R31 +R707 +L9 +L91 +R44 +L93 +R82 +L733 +L75 +R19 +R24 +L68 +L481 +R87 +R80 +R663 +L19 +L705 +L59 +R60 +R86 +R64 +R40 +L63 +R67 +R19 +R43 +R18 +L7 +R207 +L68 +R7 +L82 +L54 +L6 +L97 +L672 +L28 +L90 +R90 +L807 +R7 +L15 +R176 +L66 +L26 +L47 +L245 +R123 +R4 +L4 +R14 +R30 +R42 +R88 +L74 +R26 +R9 +R98 +R58 +R9 +L775 +L60 +R17 +L82 +R9 +L9 +L2 +L19 +L866 +R87 +L37 +R137 +R51 +R68 +L19 +L39 +L1 +R12 +L72 +L44 +L56 +L77 +R77 +R87 +R57 +R56 +R16 +R962 +R812 +R75 +R79 +R56 +R67 +L26 +L53 +R7 +R63 +R843 +L1 +R441 +L512 +R74 +R97 +R867 +R75 +L11 +L86 +L78 +R538 +R43 +L20 +L9 +R81 +L191 +R21 +R72 +R98 +R37 +L47 +L65 +R89 +R86 +R56 +R44 +L970 +R39 +L97 +R28 +L80 +R22 +L570 +L99 +L76 +R3 +R1 +R799 +L22 +R71 +L71 +R49 +L27 +R23 +R40 +R40 +L14 +L89 +L30 +L86 +L33 +L24 +R73 +L86 +L97 +R92 +R991 +L91 +L30 +L52 +L27 +R21 +L25 +L696 +L14 +R74 +R62 +L458 +R293 +L771 +R614 +L58 +L742 +R574 +R31 +R95 +R61 +L43 +L84 +R424 +L727 +R56 +L87 +R569 +R66 +L844 +L67 +R32 +R59 +R85 +R281 +R47 +L432 +L796 +L63 +R75 +R626 +L6 +L4 +L36 +R81 +R61 +R11 +L45 +R58 +L21 +R95 +L50 +L14 +L315 +R47 +L729 +R529 +L49 +R340 +L191 +R12 +L12 +R8 +L21 +R26 +R10 +R8 +R39 +R30 +L3 +R20 +L17 +L89 +R18 +R171 +R238 +L137 +L95 +L6 +L98 +R94 +L12 +R911 +L65 +L30 +R69 +R31 +R57 +R14 +L75 +L99 +R52 +L756 +L93 +R52 +R82 +L99 +L77 +R11 +L569 +R13 +R89 +L89 +R814 +R73 +L31 +R31 +L14 +L602 +L284 +L61 +L866 +R23 +L13 +L284 +L25 +R66 +R60 +L54 +L46 +R73 +L38 +R54 +R11 +R34 +L868 +L32 +L25 +L9 +L75 +R75 +L443 +R826 +L22 +L61 +L96 +R3 +R4 +L899 +R388 +L44 +R644 +L26 +L874 +L466 +L34 +R91 +L41 +L69 +L87 +R22 +R2 +R185 +L703 +L28 +R227 +L24 +L75 +L7 +R7 +L90 +L10 +R16 +R15 +L22 +R97 +L6 +R762 +L62 +R447 +R98 +L1 +L70 +L10 +R7 +R86 +R66 +R77 +R95 +R74 +L43 +R68 +L56 +L70 +L99 +L4 +L32 +R69 +L83 +R727 +L46 +R102 +L2 +L66 +L34 +L484 +L28 +R76 +L96 +L21 +L87 +R96 +L836 +R73 +L93 +R90 +R33 +R177 +L45 +R545 +R15 +L2 +L13 +R774 +L867 +R93 +L24 +R24 +L79 +R49 +L51 +L19 +R49 +R98 +R53 +R52 +R48 +R46 +R1 +R57 +L73 +L9 +L29 +L821 +R9 +L481 +R7 +R493 +R39 +R61 +L80 +L20 +L79 +L32 +R20 +L79 +R70 +L83 +L17 +L59 +L2 +R61 +L57 +L67 +L46 +R46 +R11 +R97 +L420 +R30 +L484 +R8 +R482 +L571 +L29 +R30 +R415 +R55 +R169 +L5 +R87 +L89 +R652 +L66 +L48 +R11 +R120 +L16 +L115 +L4 +L24 +R454 +R74 +L139 +R89 +L20 +L82 +L48 +L964 +R251 +R24 +L11 +R65 +R92 +L5 +R156 +R95 +L15 +R31 +L112 +R93 +L93 +R93 +L66 +L98 +R57 +L81 +L385 +L87 +R515 +L10 +R55 +L642 +R442 +R69 +L28 +L83 +L458 +R20 +R80 +R77 +R23 +L45 +R619 +R26 +L21 +R81 +R2 +R738 +R66 +R57 +L82 +L73 +R14 +L82 +L40 +R289 +L84 +R35 +L73 +R443 +R30 +R266 +R84 +R16 +R142 +R42 +R250 +R9 +L43 +R34 +L42 +R42 +L28 +R775 +R84 +L430 +L11 +L19 +L44 +R73 +R84 +R31 +R69 +L58 +L66 +R40 +L17 +L95 +R12 +R98 +L32 +R176 +R1 +R23 +R4 +L495 +R15 +L118 +L72 +L58 +R72 +L85 +L363 +L654 +L26 +R14 +L34 +R49 +R41 +R98 +R23 +R23 +L24 +R873 +L49 +L15 +R20 +R95 +R24 +L27 +L422 +L73 +R14 +L16 +L24 +L83 +R581 +L27 +L37 +L46 +R80 +R73 +R83 +L733 +L26 +L184 +L94 +R8 +L71 +R25 +L925 +L56 +R31 +R46 +R56 +L477 +L58 +L626 +R984 +R28 +L28 +L220 +L5 +L75 +R61 +L61 +R8 +R92 +L63 +R63 +R90 +L927 +R37 +R1 +R499 +L88 +R83 +L95 +R209 +R88 +L97 +R52 +L82 +R2 +R99 +L44 +R84 +R289 +R48 +R68 +R60 +R9 +R36 +L21 +L657 +R47 +L90 +R35 +L655 +L80 +R515 +L41 +L74 +R260 +L4 +R844 +R61 +L609 +L45 +R49 +R9 +L54 +L43 +L68 +R75 +R45 +R80 +R61 +R39 +R87 +L53 +L87 +L729 +R60 +L78 +R99 +R34 +L73 +R40 +L62 +R83 +L21 +L893 +L38 +R31 +L869 +R69 +L278 +R40 +L62 +R24 +R476 +R27 +L46 +R511 +L70 +L33 +L2 +R732 +L62 +R43 +R70 +L91 +R21 +R1 +R99 +R702 +R98 +L22 +L56 +R38 +L33 +L327 +L949 +R57 +R61 +R31 +L832 +L61 +R904 +R3 +L3 +L11 +L737 +R705 +L68 +R1 +L1 +R16 +L12 +R49 +R747 +L46 +L254 +R991 +L38 +L45 +L82 +R80 +L38 +L68 +R254 +L36 +L75 +R57 +L23 +L77 +R80 +R25 +R95 +L609 +R9 +L379 +L57 +L56 +L97 +R64 +L625 +R23 +R25 +R36 +L81 +L753 +R27 +L275 +L640 +L180 +R868 +R697 +L26 +L48 +L93 +R10 +L946 +R37 +L31 +L3 +L97 +L19 +L603 +L445 +R71 +R194 +L77 +L21 +L33 +L576 +L963 +R72 +R56 +R211 +R33 +R45 +L45 +R13 +R29 +R80 +R62 +R16 +L886 +L940 +L4 +R18 +L40 +R52 +R12 +L12 +R921 +R77 +R79 +R62 +R259 +L31 +L84 +L983 +R10 +R19 +R18 +L75 +L99 +L13 +R696 +R44 +R464 +L674 +R10 +R475 +L30 +R20 +L65 +L74 +R774 +L53 +L62 +L85 +L92 +L81 +L27 +L95 +R846 +R64 +R85 +L359 +R59 +L5 +L23 +R878 +L54 +R88 +R416 +R42 +R758 +L3 +L30 +L6 +R42 +R6 +L57 +L59 +L36 +R47 +R5 +L9 +L15 +R15 +L730 +R30 +R37 +R86 +R93 +L77 +R69 +L7 +L217 +L92 +R8 +R11 +R89 +L982 +L18 +L3 +L680 +L17 +R52 +L52 +L6 +R6 +L52 +R67 +R683 +L198 +R59 +R2 +R39 +L35 +R35 +R8 +R22 +R82 +R54 +R34 +L51 +L59 +R3 +L84 +L175 +R89 +R65 +R6 +L61 +L33 +R84 +R757 +L41 +R28 +L28 +R20 +L467 +R47 +L42 +L11 +R53 +L76 +R25 +L70 +R552 +L31 +R24 +R76 +L953 +R496 +L88 +R33 +R64 +R48 +L44 +R37 +R7 +L262 +R74 +R55 +R84 +R49 +R52 +R73 +R65 +L290 +R36 +L24 +R88 +R7 +L55 +R68 +L23 +R929 +R71 +L968 +R71 +R97 +R73 +R48 +R16 +R21 +L55 +R71 +L549 +L6 +R84 +L21 +R929 +L8 +L96 +L87 +L517 +R335 +R60 +L72 +L23 +R26 +R20 +R54 +R94 +L2 +R8 +L19 +L99 +L14 +L286 +R18 +L10 +R610 +L34 +L37 +L99 +L130 +R86 +L63 +R77 +L574 +L26 +R66 +R46 +L58 +L54 +R84 +R16 +L76 +R376 +R84 +L71 +L87 +L26 +R31 +R31 +L77 +L74 +L19 +L13 +R22 +L23 +L49 +R37 +L97 +R584 +R47 +R50 +R50 +L98 +L4 +L98 +L24 +L21 +L55 +L89 +R55 +L49 +R30 +R16 +R88 +L797 +R346 +L89 +R89 +R97 +L97 +R997 +R36 +L33 +L70 +R19 +R48 +L97 +L74 +L86 +L53 +L87 +R76 +R66 +L49 +R4 +L4 +L69 +L24 +L53 +R16 +R5 +R42 +L10 +R56 +L56 +R624 +L5 +R81 +L26 +L93 +R71 +L59 +R7 +R762 +L49 +L244 +L61 +L62 +R69 +L15 +R17 +R83 +L41 +L48 +L235 +L61 +L15 +L81 +R87 +R34 +L40 +L61 +R61 +L1 +R18 +R97 +R42 +L84 +L50 +R515 +R98 +R65 +R56 +R94 +L50 +R49 +L47 +L542 +L5 +R45 +L71 +R83 +R88 +R601 +R44 +L60 +L7 +R57 +R65 +L56 +R923 +R35 +L23 +R421 +R27 +L65 +R9 +R48 +L19 +R518 +R80 +R31 +R479 +R8 +R63 +R21 +R93 +R40 +R167 +L91 +R98 +R25 +L55 +L77 +L51 +L62 +R13 +R61 +L25 +L83 +L53 +L73 +L27 +R47 +L38 +R76 +L85 +R705 +L79 +R5 +L66 +L6 +L48 +R63 +R14 +L420 +R41 +L9 +R66 +R84 +R39 +L51 +R198 +L931 +R95 +L63 +R18 +R26 +L35 +L262 +R216 +R82 +R18 +L901 +R930 +R71 +L34 +R34 +R7 +L34 +R687 +L74 +R141 +L66 +L61 +L22 +L85 +L93 +L8 +L492 +L42 +L56 +L424 +L94 +R67 +L76 +L98 +R35 +R68 +R80 +R20 +R20 +R36 +R42 +L60 +R531 +L49 +L18 +L50 +R991 +R86 +L309 +R90 +L90 +L601 +R61 +R40 +L50 +L60 +L98 +R78 +R9 +R49 +L28 +L55 +R55 +R24 +L24 +R422 +L331 +R9 +R42 +R58 +L76 +L79 +L745 +L86 +R86 +L85 +L47 +L81 +L55 +L32 +L80 +L20 +L30 +R54 +L796 +L5 +R77 +R57 +R901 +R23 +R703 +R58 +L436 +L67 +L79 +R195 +L155 +L87 +R33 +R54 +R77 +L92 +L3 +L21 +R53 +L84 +R45 +L358 +R383 +L220 +L80 +L18 +L64 +L18 +R192 +R45 +L54 +L56 +L27 +R46 +R71 +R30 +R51 +L11 +L87 +R69 +L98 +R29 +L2 +L98 +L79 +L94 +L729 +L98 +L51 +R51 +R69 +R10 +L986 +R399 +L19 +L322 +L10 +R90 +L42 +L66 +R92 +R91 +L6 +R342 +R30 +L43 +R51 +R59 +R61 +L79 +L45 +R90 +L66 +R25 +L51 +L74 +R54 +R72 +R774 +R28 +R72 +L126 +R32 +L6 +R50 +R440 +L7 +L83 +L47 +L53 +R44 +R41 +R75 +R40 +L5 +L95 +L26 +L94 +L394 +R99 +L85 +L43 +R743 +R647 +R98 +L29 +L16 +L53 +L585 +L62 +L688 +R56 +L46 +L673 +R51 +L342 +L258 +L39 +L28 +L33 +L865 +L73 +R32 +R6 +R92 +L15 +R35 +R29 +L41 +L88 +R88 +L80 +L491 +R87 +L72 +L44 +R31 +R69 +R270 +R30 +R10 +L278 +R74 +R73 +L22 +R693 +L15 +L106 +L29 +R65 +R35 +L99 +L30 +R97 +L68 +L8 +R68 +L67 +R86 +R95 +R19 +R7 +R6 +L6 +R45 +R66 +R89 +L38 +R474 +R55 +R71 +R38 +L45 +L55 +R91 +L91 +R41 +L62 +R21 +R80 +R20 +L244 +L6 +R57 +L7 +L27 +R42 +L130 +L17 +L97 +L71 +R40 +L58 +R24 +R94 +L792 +L6 +R952 +L54 +L6 +L694 +R2 +R498 +L98 +R76 +R16 +R35 +R382 +L20 +L775 +L18 +R2 +R87 +L13 +R665 +L69 +L356 +R190 +L3 +R70 +R20 +L91 +R589 +L15 +L16 +R42 +R998 +L383 +L96 +R81 +R195 +L91 +L983 +R79 +L94 +L441 +R35 +R25 +L7 +R36 +L21 +R821 +R92 +R54 +R83 +L83 +R89 +L89 +R848 +L85 +R86 +L49 +L89 +L6 +L456 +R68 +L117 +R48 +L48 +R20 +R80 +R17 +R83 +R773 +R27 +R76 +R24 +L109 +L91 +L55 +R555 +L85 +L30 +R33 +L380 +R6 +L60 +L31 +L35 +R82 +L38 +L17 +R58 +R97 +R53 +L14 +L62 +L984 +R7 +L43 +R55 +R961 +L239 +R66 +L45 +L455 +L40 +L461 +L9 +L17 +L73 +R81 +L21 +L14 +R54 +L24 +R24 +L78 +R778 +R49 +L749 +L88 +L50 +L88 +R47 +R79 +L584 +L16 +R641 +R64 +R577 +R682 +L11 +L29 +L20 +R77 +L981 +R42 +L112 +R70 +R83 +R17 +L40 +R56 +R90 +R94 +R91 +R48 +R2 +L41 +L85 +L76 +R61 +R189 +L89 +R426 +R19 +L845 +L35 +L32 +L33 +R97 +L761 +L32 +R52 +R520 +R22 +L404 +R92 +R14 +L34 +R34 +L65 +L235 +L893 +R55 +L669 +R7 +L91 +R46 +L90 +R55 +L128 +R84 +L47 +L29 +R41 +R70 +R89 +L401 +R1 +L937 +R54 +L37 +L84 +R45 +R5 +L946 +R30 +R80 +R35 +R55 +R713 +R26 +L833 +L91 +R65 +L180 +R95 +L795 +L21 +L79 +R693 +L927 +R6 +R528 +L372 +L59 +R325 +L63 +L31 +R89 +L75 +L414 +R79 +L134 +L839 +L67 +L93 +R145 +L76 +R85 +L55 +L69 +L28 +L10 +R62 +L17 +L83 +L91 +R91 +R63 +L63 +R768 +L68 +L45 +L330 +R896 +R30 +L83 +R132 +R2 +L77 +R50 +R825 +L5 +R5 +L20 +R88 +L68 +R68 +L68 +R13 +R85 +L79 +R22 +R46 +L87 +R76 +L84 +L14 +L15 +L57 +R94 +L38 +L478 +L790 +L94 +R89 +R211 +R769 +L78 +R709 +R89 +R46 +R781 +R44 +L70 +L54 +L36 +R6 +R94 +R32 +L886 +L51 +L95 +L50 +R32 +R85 +R222 +L53 +R504 +L40 +L89 +R59 +L70 +R34 +L39 +R99 +R29 +R81 +L43 +R72 +L14 +R30 +L676 +L58 +R85 +R27 +L527 +L25 +L375 +L13 +R904 +L68 +L123 +L57 +L49 +R6 +L91 +R35 +L66 +L63 +R58 +L243 +R81 +L11 +L578 +R2 +R22 +L7 +L39 +R48 +L148 +L946 +L3 +L84 +R433 +L15 +R915 +L76 +L14 +R290 +L85 +R85 +L34 +L66 +R56 +R544 +R85 +R33 +R436 +L21 +R245 +R22 +R826 +L14 +L112 +R19 +R12 +L18 +R12 +L20 +R6 +L876 +L35 +L62 +L38 +R27 +L27 +R93 +L93 +L94 +R660 +L6 +R766 +R425 +R38 +R35 +R78 +L88 +R78 +L58 +R22 +L56 +L5 +L15 +R15 +L95 +R96 +R4 +L2 +R373 +L20 +L85 +R66 +R68 +R34 +L3 +L289 +L70 +L72 +R28 +L29 +L12 +R25 +R771 +L83 +L46 +R46 +R23 +R58 +R19 +R73 +L56 +R667 +R87 +L74 +L44 +L35 +R66 +L125 +L93 +R734 +L492 +R327 +L89 +L995 +R54 +L905 +L267 +R667 +L95 +L43 +R4 +R5 +L62 +L309 +R80 +L80 +L91 +R860 +R31 +R50 +L41 +L64 +L942 +R4 +L204 +L11 +R8 +R518 +R82 +R3 +R38 +R33 +R26 +R32 +R68 +R1 +L47 +L54 +L64 +R45 +L81 +L99 +L955 +R88 +L53 +L81 +R234 +R266 +L280 +R87 +R71 +L68 +L22 +R91 +R29 +R992 +L25 +R5 +R12 +R8 +L250 +L50 +L2 +R2 +R15 +R903 +R782 +R66 +R46 +L64 +L7 +L7 +L34 +L51 +R35 +L35 +L410 +R61 +L50 +L50 +R67 +L367 +R13 +R39 +L52 +L52 +L28 +R48 +R32 +L92 +R92 +R12 +L83 +R71 +R67 +R33 +L55 +R2 +R53 +L70 +R95 +L98 +L94 +R567 +L21 +R25 +L245 +L78 +L81 +L56 +L88 +R681 +R994 +R712 +R457 +L73 +R156 +L968 +R8 +R78 +R6 +L74 +L33 +R185 +R15 +L668 +R2 +L86 +L758 +L89 +L1 +R675 +L730 +L11 +L77 +L28 +L29 +L42 +L61 +R29 +L26 +R90 +R10 +L96 +L69 +L721 +L81 +L81 +L61 +R409 +L79 +R379 +L31 +R31 +R5 +R33 +L83 +R96 +L33 +R82 +L9 +L756 +L182 +L53 +L92 +L37 +R29 +L16 +R416 +R64 +L64 +L10 +R22 +R268 +L21 +R71 +L75 +R833 +L29 +R77 +R55 +L11 +L82 +R14 +L43 +L53 +L16 +R6 +R94 +L51 +R31 +R20 +L95 +R295 +R34 +L570 +L102 +R85 +R564 +L711 +R688 +L88 +R95 +L95 +R62 +R34 +R8 +R31 +R659 +L49 +L88 +R2 +R98 +L79 +R5 +L62 +R379 +R355 +L57 +L38 +R815 +L20 +L831 +R76 +L47 +R677 +R70 +R740 +R39 +R8 +L87 +R7 +R32 +R86 +R97 +R78 +R38 +R428 +R98 +L64 +L28 +R928 +L65 +L635 +R20 +L20 +L53 +R53 +R278 +R624 +R52 +L51 +R86 +L10 +L16 +L63 +L69 +R69 +L35 +L92 +L73 +R92 +L92 +L95 +R95 +R86 +R28 +L14 +R29 +L29 +L49 +L51 +R68 +R76 +L644 +R63 +R137 +R56 +L56 +R99 +R858 +R20 +L77 +R982 +L68 +R73 +R13 +R227 +R68 +R405 +L24 +R59 +L71 +L638 +R74 +L31 +L81 +R85 +L73 +R41 +R59 +L40 +L60 +R17 +L17 +L87 +L13 +R14 +R391 +L5 +L821 +R21 +L73 +R73 +R7 +R17 +R52 +L8 +R169 +R63 +L709 +R9 +R62 +R15 +L63 +R67 +L81 +R35 +R65 +R24 +L83 +L704 +R363 +L5 +L44 +R49 +L47 +L53 +L77 +L23 +R31 +L31 +R48 +L48 +L2 +R272 +L23 +L6 +L841 +L5 +L52 +R57 +L948 +L29 +L19 +R30 +L78 +L10 +L41 +L88 +L76 +L91 +R50 +L305 +L95 +L66 +R366 +R71 +L71 +R452 +R5 +L57 +R882 +L82 +R96 +R37 +L75 +R42 +L56 +L144 +L73 +R73 +R625 +L9 +L216 +R28 +L912 +R84 +L897 +R497 +R85 +L22 +L46 +L38 +R121 +R99 +L18 +R19 +L163 +L237 +L23 +R623 +L20 +R87 +L67 +L396 +L102 +R98 +R24 +R76 +R62 +R36 +L98 +R16 +R4 +L20 +L222 +L678 +R98 +L1 +R262 +L459 +L54 +L16 +R283 +L27 +R114 +L78 +R64 +R45 +R69 +L6 +R5 +L28 +R76 +L76 +R29 +R83 +L83 +R119 +R95 +L98 +R84 +R28 +R72 +L99 +R89 +L90 +R111 +L66 +R55 +R50 +R28 +R78 +R559 +R85 +L36 +R36 +R67 +R33 +R846 +L46 +R999 +L80 +L19 +L55 +L63 +R69 +L68 +L33 +R50 +L264 +R534 +L43 +R173 +L30 +L70 +L60 +R99 +L86 +R59 +L19 +L93 +R272 +R58 +L30 +L23 +R77 +L80 +L41 +R97 +L52 +L25 +L88 +R35 +R10 +R10 +L46 +L40 +L72 +L5 +L613 +R76 +R80 +L33 +L67 +L19 +R16 +L10 +R4 +L60 +R69 +R319 +L185 +L85 +L49 +L20 +L80 +R61 +L66 +L247 +L17 +R69 +L65 +R65 +R25 +L12 +L21 +L92 +L66 +L83 +R49 +L51 +L30 +L81 +L87 +L53 +R80 +L392 +L32 +L95 +R22 +L481 +L84 +L16 +L75 +R75 +L11 +R11 +R962 +L62 +R740 +L40 +R7 +L22 +L85 +R6 +L42 +R390 +R37 +R34 +R60 +R723 +L308 +L76 +L46 +L78 +R41 +L68 +L95 +R7 +R15 +L94 +R76 +L39 +R18 +L49 +R31 +R57 +L131 +R60 +R96 +R19 +L44 +R19 +R40 +R41 +R942 +L39 +R63 +L66 +R650 +R77 +L48 +R54 +L412 +R879 +R724 +L424 +R1 +L4 +R703 +L92 +L1 +R59 +R134 +R97 +R88 +L52 +R30 +L63 +R30 +L618 +R88 +R38 +R44 +R18 +R55 +R45 +R86 +R18 +L639 +R5 +L70 +R65 +R48 +L13 +L84 +R41 +L57 +R85 +L85 +L65 +L10 +R35 +R76 +L840 +R44 +L40 +R23 +R65 +L488 +R26 +R70 +L13 +R606 +R11 +R96 +R604 +R426 +R74 +L50 +R33 +R40 +R58 +L715 +R534 +R55 +R29 +L41 +R60 +R18 +R279 +R15 +L75 +L61 +L33 +L62 +R84 +L48 +R864 +R94 +R78 +R51 +R93 +L81 +L90 +L70 +L29 +L45 +L685 +R408 +R52 +L94 +L62 +L28 +R6 +R18 +R205 +L90 +R75 +R84 +L74 +R40 +L640 +L53 +R436 +R604 +R99 +L46 +R550 +L141 +R14 +L67 +L74 +L34 +R12 +L78 +R78 +L83 +L505 +R388 +L36 +L159 +L5 +R598 +L933 +L47 +R96 +R76 +L8 +L318 +R6 +L970 +L951 +R51 +L35 +L186 +R146 +L25 +R97 +R3 +L527 +R35 +L24 +L384 +R66 +L28 +L62 +L28 +R19 +R33 +L30 +R78 +L248 +R57 +R92 +R51 +R75 +R25 +L78 +R78 +L74 +R15 +L744 +L97 +L36 +L76 +R12 +L95 +R62 +L855 +L12 +R61 +L892 +R3 +R328 +L72 +L30 +L96 +L5 +R150 +L447 +L520 +R80 +R40 +R43 +R52 +L92 +R56 +R677 +L36 +R594 +R6 +L86 +L19 +L34 +R410 +L71 +R3 +R97 +R82 +R94 +L176 +R63 +R26 +R11 +R55 +R45 +R17 +R709 +L972 +L76 +R68 +L74 +L72 +L70 +R57 +L60 +L27 +L17 +L83 +R49 +L17 +R84 +L33 +R405 +R13 +R99 +L41 +L19 +L77 +L804 +L10 +L30 +L28 +L705 +R214 +R63 +R56 +R81 +R99 +R88 +R13 +L74 +L42 +R56 +R58 +L36 +L62 +L95 +L5 +R86 +R255 +R28 +R82 +L15 +L72 +L42 +L89 +L33 +L165 +R65 +L49 +L29 +L22 +R96 +R31 +L27 +R18 +R2 +L21 +L84 +L15 +L88 +L110 +R6 +R81 +R39 +L28 +R80 +L56 +L24 +L43 +R43 +R20 +R25 +R36 +R27 +L7 +R99 +L19 +L45 +R92 +L78 +R39 +L87 +R98 +R85 +R15 +R59 +L4 +R65 +R680 +R61 +R39 +R76 +R24 +R96 +L26 +L70 +R79 +R521 +L83 +L22 +L528 +L62 +L505 +L5 +R5 +R77 +R23 +L18 +R18 +R2 +L63 +L739 +L522 +R22 +L11 +L140 +R36 +L85 +L392 +L97 +L36 +R25 +R56 +L56 +R545 +R39 +L34 +L692 +L82 +R89 +R2 +R33 +L56 +R20 +L677 +L44 +R57 +R6 +R22 +L228 +L70 +R48 +R48 +L383 +R257 +L43 +L51 +R66 +L87 +R715 +L80 +L1 +L14 +R45 +R50 +R45 +L320 +R75 +L64 +L24 +R71 +L486 +L28 +L7 +L53 +L9 +L75 +R96 +R38 +L82 +R95 +R28 +L16 +R16 +R658 +R42 +L67 +L91 +L42 +R93 +R40 +L93 +L802 +L26 +R88 +R99 +R1 +L64 +R79 +L764 +R81 +R81 +L95 +R22 +R93 +R67 +L24 +L76 +R60 +R806 +L29 +L39 +L8 +L68 +R72 +R6 +L86 +R452 +L966 +R86 +R596 +R71 +L86 +R43 +L97 +L22 +R9 +R67 +L30 +R80 +R76 +R30 +R361 +R16 +R32 +R331 +L39 +R760 +R69 +R47 +L20 +R20 +L69 +L31 +L12 +R95 +L9 +L57 +R83 +L112 +L51 +L62 +L75 +R49 +R32 +L81 +L36 +R36 +L80 +L20 +L15 +R60 +R37 +R66 +R76 +R12 +R1 +R63 +R38 +L38 +R24 +L24 +R121 +L21 +R645 +L5 +L263 +R23 +R21 +L621 +R815 +L79 +L47 +R11 +R52 +R48 +R12 +L72 +L849 +R26 +R706 +R77 +R848 +L81 +R646 +R16 +R71 +L87 +L60 +R18 +L71 +L20 +R20 +R96 +L42 +L47 +L452 +R77 +R22 +L149 +R95 +R5 +R478 +L83 +R54 +R46 +L497 +R517 +R80 +R353 +L82 +R29 +L40 +R40 +R516 +L16 +R922 +L22 +L32 +R89 +R74 +L55 +L76 +R78 +R78 +L70 +R14 +L88 +L912 +R369 +R9 +R29 +L74 +L833 +L37 +R737 +R87 +L787 +R95 +R38 +L61 +L67 +R295 +R3 +R97 +R27 +L82 +R64 +R691 +L56 +R136 +L72 +R49 +L77 +R61 +R59 +R29 +L932 +L44 +R42 +R299 +R709 +L471 +R88 +R80 +R63 +R39 +R998 +R66 +L730 +L83 +L53 +R88 +R10 +R2 +R31 +L57 +R86 +R725 +R879 +L13 +R70 +L21 +R20 +L20 +R61 +R739 +R10 +L10 +R221 +L23 +R734 +R10 +L42 +R458 +R842 +R2 +R24 +R452 +R291 +L32 +L37 +L98 +L2 +L48 +R15 +R51 +L20 +R2 +L169 +R169 +L42 +L58 +L9 +L19 +R28 +R804 +R96 +R74 +R26 +L61 +R61 +L41 +L53 +R94 +L15 +L85 +L19 +L81 +L68 +R84 +R84 +L12 +L88 +L12 +L52 +L30 +R94 +L60 +R10 +L50 +R457 +R72 +R71 +R16 +L43 +R66 +R4 +L35 +R73 +L88 +R507 +R54 +R37 +R4 +L19 +L14 +L14 +R52 +R36 +R51 +L87 +L876 +R62 +R14 +R45 +L30 +R84 +R1 +R86 +R71 +R43 +R39 +L39 +L65 +R65 +R387 +L389 +L8 +R91 +R55 +R3 +L39 +L10 +L70 +R52 +L8 +R36 +R65 +L99 +L5 +R64 +R117 +R38 +R63 +L43 +L66 +R66 +L76 +L24 +L7 +L32 +R1 +R31 +R3 +L359 +L37 +R90 +L190 +R196 +R4 +L71 +R99 +R72 +R91 +R9 +R10 +L44 +L57 +L69 +R60 +L36 +R77 +L21 +L85 +R65 +R77 +R68 +L71 +R43 +R34 +R249 +L58 +R307 +R51 +R72 +L384 +R12 +L33 +R5 +L37 +R65 +L808 +R508 +L870 +R70 +R95 +L95 +R16 +R84 +R39 +R16 +L73 +R18 +R60 +R76 +L89 +R53 +L96 +L85 +R44 +R519 +R98 +L383 +R3 +R12 +L12 +R84 +L108 +L76 +L10 +R710 +R44 +L44 +R97 +R3 +L54 +R25 +L43 +L528 +L47 +L53 +R78 +L954 +L24 +L16 +R16 +R66 +L66 +L526 +R832 +R194 +L634 +L9 +R71 +R7 +R31 +L67 +L16 +R17 +L27 +R27 +L95 +L5 +L70 +R70 +R93 +L418 +R36 +L51 +R13 +R29 +R98 +L77 +L37 +L153 +R67 +R74 +R90 +R25 +R711 +R5 +L252 +R1 +R17 +R80 +L29 +R73 +L8 +R613 +R92 +R15 +R93 +R504 +R6 +R34 +L70 +R42 +R384 +L21 +L902 +L64 +L64 +L49 +R3 +R97 +L9 +L885 +R11 +L64 +L52 +R7 +L50 +L80 +R8 +R58 +R25 +L16 +L253 +R16 +R78 +R32 +R174 +L84 +R56 +L10 +L16 +L528 +R778 +R36 +L48 +L36 +R52 +R74 +L47 +L58 +L69 +L95 +L105 +L828 +R415 +L28 +L87 +L2 +R30 +L471 +R78 +R71 +R88 +R34 +R12 +R88 +R52 +R48 +R519 +R81 +R44 +R56 +R77 +R56 +R71 +R90 +L94 +L673 +L65 +R38 +L212 +L38 +L50 +L641 +L59 +L394 +R28 +R65 +L708 +L20 +L4 +R473 +R30 +R731 +R99 +L82 +R89 +L35 +R10 +L82 +L99 +L1 +R98 +L19 +L79 +L52 +L48 +L471 +L29 +L4 +L96 +L41 +L23 +L36 +L35 +R35 +R27 +R73 +R64 +R33 +R32 +L29 +R46 +L66 +R211 +R868 +L59 +R17 +R21 +R27 +R521 +R91 +R23 +R1 +L79 +R23 +L45 +R85 +R15 +R41 +R559 +L17 +L40 +R86 +L45 +L39 +R56 +L30 +R81 +L33 +R82 +L1 +L631 +R531 +R56 +R92 +L90 +R42 +L94 +L28 +L40 +R662 +L232 +L68 +L65 +R37 +R28 +L48 +L99 +R83 +L76 +L95 +L424 +L572 +R99 +R68 +L20 +R84 +L911 +R3 +L91 +R99 +R47 +L147 +R312 +L61 +R949 +R74 +L88 +L307 +R53 +R4 +R64 +L3 +R99 +L31 +L28 +R63 +L70 +R6 +L77 +R22 +L212 +L69 +L86 +R86 +L27 +R56 +L29 +L999 +R99 +R83 +L15 +R99 +R67 +R19 +R42 +R7 +R62 +L831 +R1 +L51 +R955 +L13 +R92 +R4 +R720 +R26 +L71 +R4 +R37 +R520 +R43 +L90 +L20 +R98 +R376 +L3 +R39 +L37 +L32 +R9 +R33 +L32 +R465 +R794 +R19 +R81 +R80 +R20 +R7 +R593 +R29 +L29 +L21 +L79 +R27 +R673 +R63 +L79 +L84 +R62 +L62 +L52 +R52 +R57 +L12 +R55 +R69 +R8 +R52 +L71 +R23 +R50 +R73 +R959 +L91 +R7 +L715 +R93 +R92 +R951 +R42 +L42 +L69 +L31 +R14 +L814 +L903 +R67 +R68 +R77 +R1 +L66 +L44 +L63 +L37 +R19 +L40 +R34 +L43 +L14 +R16 +R62 +L83 +R49 +R12 +L12 +R73 +R27 +L60 +L65 +R14 +R567 +L56 +L8 +L171 +L14 +L785 +L41 +R99 +L19 +L61 +L54 +L43 +R96 +L321 +R79 +R73 +R22 +L54 +L98 +R22 +R78 +L72 +R67 +L95 +R96 +L97 +R75 +R43 +R183 +L31 +R198 +L467 +R426 +R98 +R89 +L13 +R531 +L13 +L19 +R15 +R886 +R49 +L95 +L98 +R34 +L90 +L99 +L1 +L876 +R76 +L910 +R65 +R45 +R53 +R784 +R91 +R78 +R9 +L642 +L71 +L1 +R10 +L11 +R79 +L93 +R69 +L55 +R878 +R55 +L97 +R59 +R805 +L21 +L25 +L27 +R73 +R91 +L447 +L550 +R35 +R6 +R44 +R55 +L834 +R77 +L73 +L4 +R75 +L10 +L883 +L60 +L95 +R73 +L25 +R48 +R877 +R67 +L67 +R98 +R302 +R93 +R29 +R78 +L17 +L69 +R86 +R19 +R51 +R853 +L37 +R14 +L921 +L61 +R63 +L681 +R54 +L62 +L92 +L40 +L79 +L81 +L81 +R54 +R790 +L4 +L75 +R560 +L44 +R33 +R64 +L80 +L98 +R45 +R4 +L68 +L63 +R69 +R25 +L66 +R36 +R55 +L56 +L97 +R97 +L42 +R42 +L58 +L42 +R19 +R4 +L12 +L32 +R78 +L57 +R74 +R24 +L8 +L90 +L61 +R61 +L39 +L36 +L25 +R79 +L18 +L86 +R30 +L62 +L19 +L24 +L88 +R99 +R53 +R75 +R44 +L14 +L45 +R29 +L46 +R95 +R66 +L70 +L44 +L46 +L17 +L45 +R22 +R29 +L27 +R40 +R32 +R18 +L11 +L24 +R36 +R5 +R42 +L27 +L35 +L29 +L42 +R38 +R10 +L20 +L24 +R20 +R38 +L29 +L28 +L23 +R28 +R9 +L48 +L9 +R23 +L50 +L5 +R22 +R46 +R12 +R23 +L32 +R26 +L3 +L47 +R7 +L4 +R21 +L47 +R3 +L14 +R24 diff --git a/input/day01_example.txt b/input/day01_example.txt new file mode 100644 index 0000000000000000000000000000000000000000..53287c7b25e4636b459eaa50a4e514f7405c07ec --- /dev/null +++ b/input/day01_example.txt @@ -0,0 +1,10 @@ +L68 +L30 +R48 +L5 +R60 +L55 +L1 +L99 +R14 +L82 diff --git a/manifest.toml b/manifest.toml new file mode 100644 index 0000000000000000000000000000000000000000..b98d03f01cc245c201318a3dce94f1330f841a3d --- /dev/null +++ b/manifest.toml @@ -0,0 +1,21 @@ +# This file was generated by Gleam +# You typically do not need to edit this file + +packages = [ + { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" }, + { name = "birl", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_regexp", "gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "2AC7BA26F998E3DFADDB657148BD5DDFE966958AD4D6D6957DD0D22E5B56C400" }, + { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" }, + { name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" }, + { name = "gleam_stdlib", version = "0.67.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "6368313DB35963DC02F677A513BB0D95D58A34ED0A9436C8116820BF94BE3511" }, + { name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" }, + { name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" }, + { name = "ranger", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_yielder"], otp_app = "ranger", source = "hex", outer_checksum = "C8988E8F8CDBD3E7F4D8F2E663EF76490390899C2B2885A6432E942495B3E854" }, + { name = "simplifile", version = "2.3.1", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "957E0E5B75927659F1D2A1B7B75D7B9BA96FAA8D0C53EA71C4AD9CD0C6B848F6" }, +] + +[requirements] +argv = { version = ">= 1.0.2 and < 2.0.0" } +birl = { version = ">= 1.8.0 and < 2.0.0" } +gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" } +gleeunit = { version = ">= 1.0.0 and < 2.0.0" } +simplifile = { version = ">= 2.3.1 and < 3.0.0" } diff --git a/mix.exs b/mix.exs new file mode 100644 index 0000000000000000000000000000000000000000..64db7e82fcb16043639ea7d1de6b9658dc083385 --- /dev/null +++ b/mix.exs @@ -0,0 +1,15 @@ +defmodule Aoc.MixProject do + use Mix.Project + + def project do + [ + app: :aoc, + version: "1.0.0", + deps: deps() + ] + end + + defp deps do + [] + end +end diff --git a/src/aoc.gleam b/src/aoc.gleam new file mode 100644 index 0000000000000000000000000000000000000000..0e246ae7bee113ef8390f65f9cd1d797c62856ba --- /dev/null +++ b/src/aoc.gleam @@ -0,0 +1,84 @@ +import argv +import compare +import gleam/int +import gleam/io +import gleam/list +import gleam/option.{type Option, None, Some} +import gleam/result +import gleam/string +import internal/mine/day01 as mine_day01 +import utils + +const available_days = [1] + +pub fn main() -> Nil { + let args = argv.load().arguments + + case parse_args(args) { + Error(msg) -> io.println("Error: " <> msg) + Ok(#(day, example, cmp)) -> + case day { + Some(d) -> run_day(d, example, cmp) + None -> list.each(available_days, fn(d) { run_day(d, example, cmp) }) + } + } +} + +pub type Args { + Args(day: Option(Int), example: Bool, compare: Bool) +} + +fn parse_args( + args: List(String), +) -> Result(#(Option(Int), Bool, Bool), String) { + let example = list.contains(args, "--example") || list.contains(args, "-e") + let no_cmp = + list.contains(args, "--no-compare") || list.contains(args, "-n") + let day_args = list.filter(args, fn(a) { !string.starts_with(a, "-") }) + + use day <- result.try(case day_args { + [day_str, ..] -> + case int.parse(day_str) { + Ok(d) if d >= 1 && d <= 25 -> Ok(Some(d)) + Ok(_) -> Error("day must be between 1 and 25") + Error(_) -> Error("invalid day number: " <> day_str) + } + [] -> Ok(None) + }) + + Ok(#(day, example, !no_cmp)) +} + +fn run_day(day: Int, example: Bool, cmp: Bool) -> Nil { + case utils.read_input(day, example) { + Error(e) -> io.println(e) + Ok(input) -> { + let mode = case example { + True -> " (example)" + False -> "" + } + io.println("=== Day " <> int.to_string(day) <> mode <> " ===") + case cmp { + True -> run_comparison(day, input) + False -> run_parts(day, input) + } + } + } +} + +fn run_parts(day: Int, input: List(String)) -> Nil { + case day { + 1 -> { + io.println("Part 1: " <> int.to_string(mine_day01.part1(input))) + io.println("Part 2: " <> int.to_string(mine_day01.part2(input))) + } + _ -> io.println("Day " <> int.to_string(day) <> " not implemented yet") + } +} + +fn run_comparison(day: Int, input: List(String)) -> Nil { + case day { + 1 -> compare.day01(input) + _ -> io.println("Day " <> int.to_string(day) <> " comparison not available") + } +} diff --git a/src/compare.gleam b/src/compare.gleam new file mode 100644 index 0000000000000000000000000000000000000000..cfd125b72ea3077f1b528fcd79490f1adcf61f60 --- /dev/null +++ b/src/compare.gleam @@ -0,0 +1,96 @@ +import birl +import gleam/int +import gleam/io +import gleam/string +import internal/llm/day01 as llm_day01 +import internal/mine/day01 as mine_day01 + +pub type TimedResult { + TimedResult(result: Int, microseconds: Int) +} + +fn time_fn(f: fn() -> Int) -> TimedResult { + let start = birl.now() |> birl.to_unix_micro + let result = f() + let end = birl.now() |> birl.to_unix_micro + TimedResult(result: result, microseconds: end - start) +} + +fn format_time(microseconds: Int) -> String { + case microseconds { + us if us < 1000 -> int.to_string(us) <> "µs" + us if us < 1_000_000 -> { + let ms = us / 1000 + let remainder = us % 1000 + int.to_string(ms) + <> "." + <> string.pad_start(int.to_string(remainder / 100), 1, "0") + <> "ms" + } + us -> { + let s = us / 1_000_000 + let ms = { us % 1_000_000 } / 1000 + int.to_string(s) + <> "." + <> string.pad_start(int.to_string(ms), 3, "0") + <> "s" + } + } +} + +fn print_comparison(part: String, mine: TimedResult, llm: TimedResult) -> Nil { + io.println("") + io.println("--- " <> part <> " ---") + io.println( + "Mine: " + <> int.to_string(mine.result) + <> " (" + <> format_time(mine.microseconds) + <> ")", + ) + io.println( + "LLM: " + <> int.to_string(llm.result) + <> " (" + <> format_time(llm.microseconds) + <> ")", + ) + + let match = case mine.result == llm.result { + True -> "✓ Results match" + False -> "✗ Results differ!" + } + io.println(match) + + let speedup = case mine.microseconds, llm.microseconds { + 0, 0 -> "Both too fast to measure" + m, _l if m == 0 -> "Mine too fast to measure" + _m, l if l == 0 -> "LLM too fast to measure" + m, l if m < l -> "Mine " <> format_speedup(l, m) <> " faster" + m, l if l < m -> "LLM " <> format_speedup(m, l) <> " faster" + _, _ -> "Same speed" + } + io.println(speedup) +} + +fn format_speedup(slower: Int, faster: Int) -> String { + let ratio = { slower * 100 } / faster + let whole = ratio / 100 + let frac = ratio % 100 + int.to_string(whole) + <> "." + <> string.pad_start(int.to_string(frac), 2, "0") + <> "x" +} + +pub fn day01(input: List(String)) -> Nil { + io.println("Comparing implementations...") + + let mine_p1 = time_fn(fn() { mine_day01.part1(input) }) + let llm_p1 = time_fn(fn() { llm_day01.part1(input) }) + print_comparison("Part 1", mine_p1, llm_p1) + + let mine_p2 = time_fn(fn() { mine_day01.part2(input) }) + let llm_p2 = time_fn(fn() { llm_day01.part2(input) }) + print_comparison("Part 2", mine_p2, llm_p2) +} diff --git a/src/internal/llm/day01.gleam b/src/internal/llm/day01.gleam new file mode 100644 index 0000000000000000000000000000000000000000..69e5e5d0b1d571a174e09f08b3355123faeedef2 --- /dev/null +++ b/src/internal/llm/day01.gleam @@ -0,0 +1,83 @@ +//// Authored-by: Claude Opus 4.5 via Crush + +import gleam/int +import gleam/list +import gleam/result +import gleam/string + +pub type Rotation { + Left(Int) + Right(Int) +} + +fn parse_rotation(s: String) -> Result(Rotation, Nil) { + let s = string.trim(s) + case string.first(s) { + Ok("L") -> s |> string.drop_start(1) |> int.parse |> result.map(Left) + Ok("R") -> s |> string.drop_start(1) |> int.parse |> result.map(Right) + _ -> Error(Nil) + } +} + +fn apply_rotation(position: Int, rotation: Rotation) -> Int { + let new_pos = case rotation { + Left(n) -> position - n + Right(n) -> position + n + } + // Wrap around 0-99 (100 positions) + { { new_pos % 100 } + 100 } % 100 +} + +pub fn part1(input: List(String)) -> Int { + let rotations = list.filter_map(input, parse_rotation) + let #(zero_count, _final_pos) = + list.fold(rotations, #(0, 50), fn(acc, rotation) { + let #(count, pos) = acc + let new_pos = apply_rotation(pos, rotation) + let new_count = case new_pos { + 0 -> count + 1 + _ -> count + } + #(new_count, new_pos) + }) + zero_count +} + +fn count_zeros_crossed(position: Int, rotation: Rotation) -> Int { + let #(steps, going_right) = case rotation { + Left(n) -> #(n, False) + Right(n) -> #(n, True) + } + + case going_right { + True -> { + // Right: hit 0 when (position + k) % 100 == 0 + let first_hit = { 100 - position } % 100 + case first_hit { + 0 -> steps / 100 + f if f <= steps -> { steps - f } / 100 + 1 + _ -> 0 + } + } + False -> { + // Left: hit 0 when (position - k) % 100 == 0, i.e., k == position + case position { + 0 -> steps / 100 + p if p <= steps -> { steps - p } / 100 + 1 + _ -> 0 + } + } + } +} + +pub fn part2(input: List(String)) -> Int { + let rotations = list.filter_map(input, parse_rotation) + let #(zero_count, _final_pos) = + list.fold(rotations, #(0, 50), fn(acc, rotation) { + let #(count, pos) = acc + let zeros = count_zeros_crossed(pos, rotation) + let new_pos = apply_rotation(pos, rotation) + #(count + zeros, new_pos) + }) + zero_count +} diff --git a/src/internal/mine/day01.gleam b/src/internal/mine/day01.gleam new file mode 100644 index 0000000000000000000000000000000000000000..2049c4e21b46f5c9eb1e25d21f23b6276c631943 --- /dev/null +++ b/src/internal/mine/day01.gleam @@ -0,0 +1,90 @@ +import gleam/int +import gleam/list +import gleam/result +import gleam/string + +const starting_position = 50 + +pub type Movement { + Left(Int) + Right(Int) +} + +pub fn part1(input: List(String)) -> Int { + let movements = input |> list.filter_map(parse_movement) + let #(zero_count, _final_pos) = + list.fold(movements, #(0, starting_position), fn(acc, movement) { + let #(count, pos) = acc + let new_pos = apply_movement(pos, movement) + let new_count = case new_pos { + 0 -> count + 1 + _ -> count + } + #(new_count, new_pos) + }) + zero_count +} + +pub fn part2(input: List(String)) -> Int { + let movements = input |> list.filter_map(parse_movement) + let #(zero_count, _final_pos) = + list.fold(movements, #(0, starting_position), fn(acc, movement) { + let #(count, pos) = acc + let new_pos = apply_movement(pos, movement) + let zeroes = zeroes_hit(pos, movement) + #(count + zeroes, new_pos) + }) + zero_count +} + +pub fn parse_movement(input: String) -> Result(Movement, Nil) { + case string.first(input) { + Ok("L") -> + input + |> string.drop_start(1) + |> int.parse + |> result.map(Left) + Ok("R") -> + input + |> string.drop_start(1) + |> int.parse + |> result.map(Right) + _ -> Error(Nil) + } +} + +fn apply_movement(position: Int, movement: Movement) -> Int { + let new_pos = case movement { + Left(n) -> position - n + Right(n) -> position + n + } + // Wrap around 0-99 (100 positions) + { { new_pos % 100 } + 100 } % 100 +} + +fn zeroes_hit(position: Int, movement: Movement) -> Int { + let #(steps, going_right) = case movement { + Left(n) -> #(n, False) + Right(n) -> #(n, True) + } + + case going_right { + True -> { + // Right: hit 0 when (position + k) % 100 == 0 + let first_hit = { 100 - position } % 100 + case first_hit { + 0 -> steps / 100 + f if f <= steps -> { steps - f } / 100 + 1 + _ -> 0 + } + } + False -> { + // Left: hit 0 when (position - k) % 100 == 0, i.e., k == position + case position { + 0 -> steps / 100 + p if p <= steps -> { steps - p } / 100 + 1 + _ -> 0 + } + } + } +} diff --git a/src/utils.gleam b/src/utils.gleam new file mode 100644 index 0000000000000000000000000000000000000000..dd2587b6e1fc9cf381f1c8e8586c8114c1100c1f --- /dev/null +++ b/src/utils.gleam @@ -0,0 +1,23 @@ +import gleam/int +import gleam/string +import simplifile + +/// Read input for a given day. If example is True, reads from dayXX_example.txt +pub fn read_input(day: Int, example: Bool) -> Result(List(String), String) { + let day_str = int.to_string(day) |> string.pad_start(2, "0") + let suffix = case example { + True -> "_example" + False -> "" + } + let path = "input/day" <> day_str <> suffix <> ".txt" + + case simplifile.read(path) { + Ok(content) -> + Ok( + content + |> string.trim + |> string.split("\n"), + ) + Error(e) -> Error("failed to read " <> path <> ": " <> string.inspect(e)) + } +} diff --git a/test/aoc_test.gleam b/test/aoc_test.gleam new file mode 100644 index 0000000000000000000000000000000000000000..5f14bb970ed374a017ad20f2478b98f7dee3d4b2 --- /dev/null +++ b/test/aoc_test.gleam @@ -0,0 +1,39 @@ +import gleeunit +import gleeunit/should +import internal/llm/day01 as llm_day01 +import internal/mine/day01 as mine_day01 +import utils + +pub fn main() -> Nil { + gleeunit.main() +} + +pub fn mine_day01_part1_example_test() { + let assert Ok(input) = utils.read_input(1, True) + mine_day01.part1(input) + |> should.equal(3) +} + +pub fn mine_day01_part1_test() { + let assert Ok(input) = utils.read_input(1, False) + mine_day01.part1(input) + |> should.equal(1011) +} + +pub fn llm_day01_part1_example_test() { + let assert Ok(input) = utils.read_input(1, True) + llm_day01.part1(input) + |> should.equal(3) +} + +pub fn llm_day01_part1_test() { + let assert Ok(input) = utils.read_input(1, False) + llm_day01.part1(input) + |> should.equal(1011) +} + +pub fn llm_day01_part2_example_test() { + let assert Ok(input) = utils.read_input(1, True) + llm_day01.part2(input) + |> should.equal(6) +}