2025: day01

This commit is contained in:
Antoine Martin 2025-12-01 15:03:54 +01:00
parent d9c8d8155c
commit bf06dccb94
8 changed files with 4574 additions and 1 deletions

8
Cargo.lock generated
View file

@ -133,6 +133,14 @@ dependencies = [
"criterion 0.4.0", "criterion 0.4.0",
] ]
[[package]]
name = "aoc2025"
version = "0.1.0"
dependencies = [
"anyhow",
"aoc",
]
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"

View file

@ -1,7 +1,7 @@
[workspace] [workspace]
members = ["aoc20*", "aoc20*/aoc20*_bench"] members = ["aoc20*", "aoc20*/aoc20*_bench"]
default-members = ["aoc2023"] default-members = ["aoc2025"]
resolver = "2" resolver = "2"

16
aoc2025/Cargo.toml Normal file
View file

@ -0,0 +1,16 @@
[package]
name = "aoc2025"
version = "0.1.0"
authors = ["Antoine Martin <antoine@alarsyo.net>"]
edition = "2024"
[dependencies]
aoc = { path = "../aoc" }
anyhow = "1.0"
[lib]
path = "src/lib.rs"
[[bin]]
name = "aoc2025"
path = "src/main.rs"

4392
aoc2025/input/day01.txt Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
L68
L30
R48
L5
R60
L55
L1
L99
R14
L82

135
aoc2025/src/day01.rs Normal file
View file

@ -0,0 +1,135 @@
use std::{fmt::Write, str::FromStr};
use anyhow::{bail, Result};
const INPUT: &str = include_str!("../input/day01.txt");
const DIAL_SIZE: u16 = 100;
pub fn run() -> Result<String> {
let mut res = String::with_capacity(128);
writeln!(res, "part 1: {}", part1(INPUT)?)?;
writeln!(res, "part 2: {}", part2(INPUT)?)?;
Ok(res)
}
enum Rotation {
Left(u16),
Right(u16),
}
impl FromStr for Rotation {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self> {
let dir = &s[..1];
let num = s[1..].parse()?;
match dir {
"L" => Ok(Rotation::Left(num)),
"R" => Ok(Rotation::Right(num)),
_ => bail!("rotation can only be left or right, got `{}'", dir),
}
}
}
impl Rotation {
fn apply(&self, state: u16) -> u16 {
match self {
Rotation::Left(num) => {
let num = num % DIAL_SIZE;
if num > state {
DIAL_SIZE - (num - state)
} else {
state - num
}
}
Rotation::Right(num) => (state + num) % DIAL_SIZE,
}
}
/// Counts the number of zeroes encountered while rotating the dial. Does NOT take the final
/// result into account if it is 0.
fn apply_and_count_zeroes(&self, state: u16) -> (u16, usize) {
match self {
Rotation::Left(num) => {
let zeroes = (num / DIAL_SIZE) as usize;
let num = num % DIAL_SIZE;
if num > state {
(
DIAL_SIZE - (num - state),
zeroes + if state != 0 { 1 } else { 0 },
)
} else {
let new_state = state - num;
(new_state, zeroes + if new_state == 0 { 1 } else { 0 })
}
}
Rotation::Right(num) => (
(state + num) % DIAL_SIZE,
((state + num) / DIAL_SIZE) as usize,
),
}
}
}
fn part1(input: &str) -> Result<usize> {
let rotations = input
.lines()
.map(Rotation::from_str)
.collect::<Result<Vec<Rotation>>>()?;
let res = rotations
.iter()
.fold((50, 0), |(state, mut count), rot| {
let new_state = rot.apply(state);
if new_state == 0 {
count += 1;
}
(new_state, count)
})
.1;
Ok(res)
}
fn part2(input: &str) -> Result<usize> {
let rotations = input
.lines()
.map(Rotation::from_str)
.collect::<Result<Vec<Rotation>>>()?;
let res = rotations
.iter()
.fold((50, 0), |(state, count), rot| {
let (new_state, zeroes) = dbg!(rot.apply_and_count_zeroes(state));
(new_state, count + zeroes)
})
.1;
Ok(res)
}
#[cfg(test)]
mod tests {
use super::*;
const PROVIDED: &str = include_str!("../input/day01_provided.txt");
#[test]
fn part1_provided() {
assert_eq!(part1(PROVIDED).unwrap(), 3);
}
#[test]
fn part1_real() {
assert_eq!(part1(INPUT).unwrap(), 1092);
}
#[test]
fn part2_provided() {
assert_eq!(part2(PROVIDED).unwrap(), 6);
}
#[test]
fn part2_real() {
assert_eq!(part2(INPUT).unwrap(), 6616);
}
}

1
aoc2025/src/lib.rs Normal file
View file

@ -0,0 +1 @@
pub mod day01;

11
aoc2025/src/main.rs Normal file
View file

@ -0,0 +1,11 @@
use anyhow::Result;
use aoc::DayFunc;
use aoc2025::day01;
fn main() -> Result<()> {
let days: &[DayFunc] = &[day01::run];
aoc::run(days)
}