From 91d9d7b1dc944810c85ae0fc8db31b55dc1cb51b Mon Sep 17 00:00:00 2001 From: Jan-Bulthuis Date: Mon, 1 Dec 2025 06:21:24 +0100 Subject: [PATCH] feat: Day 1 --- .gitignore | 3 +- aoc_2025/Cargo.lock | 149 +++++++++++++++++++++++++++++++++++++++ aoc_2025/Cargo.toml | 11 +++ aoc_2025/README.md | 3 + aoc_2025/src/day1.rs | 121 +++++++++++++++++++++++++++++++ aoc_2025/src/lib.rs | 36 ++++++++++ aoc_2025/src/template.rs | 46 ++++++++++++ 7 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 aoc_2025/Cargo.lock create mode 100644 aoc_2025/Cargo.toml create mode 100644 aoc_2025/README.md create mode 100644 aoc_2025/src/day1.rs create mode 100644 aoc_2025/src/lib.rs create mode 100644 aoc_2025/src/template.rs diff --git a/.gitignore b/.gitignore index e58bf05..1b931a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ */target/ */input/ -*.out \ No newline at end of file +*.out +.direnv \ No newline at end of file diff --git a/aoc_2025/Cargo.lock b/aoc_2025/Cargo.lock new file mode 100644 index 0000000..276a799 --- /dev/null +++ b/aoc_2025/Cargo.lock @@ -0,0 +1,149 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "aoc_2025" +version = "0.1.0" +dependencies = [ + "hashbrown", + "num", + "num-modular", + "topological-sort", + "winnow", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-modular" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "topological-sort" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" + +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] diff --git a/aoc_2025/Cargo.toml b/aoc_2025/Cargo.toml new file mode 100644 index 0000000..64931fa --- /dev/null +++ b/aoc_2025/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "aoc_2025" +version = "0.1.0" +edition = "2024" + +[dependencies] +hashbrown = "0.16.1" +num = "0.4.3" +num-modular = "0.6.1" +topological-sort = "0.2.2" +winnow = "0.7.14" diff --git a/aoc_2025/README.md b/aoc_2025/README.md new file mode 100644 index 0000000..1ef82d5 --- /dev/null +++ b/aoc_2025/README.md @@ -0,0 +1,3 @@ +```bash +bacon test -- dayN +``` \ No newline at end of file diff --git a/aoc_2025/src/day1.rs b/aoc_2025/src/day1.rs new file mode 100644 index 0000000..51b0e9b --- /dev/null +++ b/aoc_2025/src/day1.rs @@ -0,0 +1,121 @@ +use crate::AoC; +use winnow::{ + Parser, Result, + ascii::{digit1, multispace0}, + combinator::{alt, preceded, repeat}, +}; + +type Parsed = Vec; +enum Side { + Left(i64), + Right(i64), +} + +const AOC: AoC = AoC::new(parse, part1, part2); + +fn parse(input: String) -> Parsed { + let mut input: &str = input.as_str(); + repeat(1.., parse_line).parse_next(&mut input).unwrap() +} + +fn parse_line(input: &mut &str) -> Result { + preceded(multispace0, alt((parse_left, parse_right))).parse_next(input) +} + +fn parse_left(input: &mut &str) -> Result { + preceded("L", digit1.parse_to()) + .map(Side::Left) + .parse_next(input) +} + +fn parse_right(input: &mut &str) -> Result { + preceded("R", digit1.parse_to()) + .map(Side::Right) + .parse_next(input) +} + +fn part1(input: &Parsed) -> String { + let mut res = 0; + let mut pos = 50i64; + for change in input { + match change { + Side::Left(dx) => pos = (pos + 100 - dx) % 100, + Side::Right(dx) => pos = (pos + dx) % 100, + } + if pos == 0 { + res += 1 + } + } + format!("{res}") +} + +fn part2(input: &Parsed) -> String { + let input = input + .iter() + .flat_map(|side| match side { + Side::Left(dx) => (0..*dx).map(|i| Side::Left(1)).collect::>(), + Side::Right(dx) => (0..*dx).map(|i| Side::Right(1)).collect::>(), + }) + .collect::>(); + let mut res = 0; + let mut pos = 50i64; + for change in input { + match change { + Side::Left(dx) => pos = (pos + 100 - dx) % 100, + Side::Right(dx) => pos = (pos + dx) % 100, + } + if pos == 0 { + res += 1 + } + } + format!("{res}") +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_test() { + AOC.assert1( + "L68 +L30 +R48 +L5 +R60 +L55 +L1 +L99 +R14 +L82", + "3", + ); + } + + #[test] + fn part1_solve() { + AOC.assert1(include_str!("../input/day1.txt"), "982"); + } + + #[test] + fn part2_test() { + AOC.assert2( + "L68 +L30 +R48 +L5 +R60 +L55 +L1 +L99 +R14 +L82", + "6", + ); + } + + #[test] + fn part2_solve() { + AOC.assert2(include_str!("../input/day1.txt"), "6106"); + } +} diff --git a/aoc_2025/src/lib.rs b/aoc_2025/src/lib.rs new file mode 100644 index 0000000..4f4d5ea --- /dev/null +++ b/aoc_2025/src/lib.rs @@ -0,0 +1,36 @@ +#![allow(dead_code)] +#![allow(unused)] + +mod day1; + +struct AoC { + parse: fn(String) -> T, + part1: fn(&T) -> String, + part2: fn(&T) -> String, +} + +impl AoC { + const fn new(parse: fn(String) -> T, part1: fn(&T) -> String, part2: fn(&T) -> String) -> Self { + Self { + parse, + part1, + part2, + } + } + + fn assert1(&self, input: &str, output: &str) { + let parsed = (self.parse)(input.into()); + assert_eq!((self.part1)(&parsed), output); + } + + fn assert2(&self, input: &str, output: &str) { + let parsed = (self.parse)(input.into()); + assert_eq!((self.part2)(&parsed), output); + } + + fn apply(&self, input: &str) { + let parsed = (self.parse)(input.into()); + println!("Part 1: {}", (self.part1)(&parsed)); + println!("Part 2: {}", (self.part2)(&parsed)); + } +} diff --git a/aoc_2025/src/template.rs b/aoc_2025/src/template.rs new file mode 100644 index 0000000..0a3c70f --- /dev/null +++ b/aoc_2025/src/template.rs @@ -0,0 +1,46 @@ +use crate::AoC; +use winnow::{Parser, Result}; + +type Parsed = String; + +const AOC: AoC = AoC::new(parse, part1, part2); + +fn parse(input: String) -> Parsed { + let mut input: &str = input.as_str(); + String::new() +} + +fn part1(input: &Parsed) -> String { + let res = 0; + format!("{res}") +} + +fn part2(input: &Parsed) -> String { + let res = 0; + format!("{res}") +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_test() { + AOC.assert1("", ""); + } + + #[test] + fn part1_solve() { + AOC.assert1(include_str!("../input/day1.txt"), ""); + } + + // #[test] + // fn part2_test() { + // AOC.assert2("", ""); + // } + + // #[test] + // fn part2_solve() { + // AOC.assert2(include_str!("../input/day1.txt"), ""); + // } +}