Initial commit: day01 solved
This commit is contained in:
10
src/day01/input/test1.txt
Normal file
10
src/day01/input/test1.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
L68
|
||||
L30
|
||||
R48
|
||||
L5
|
||||
R60
|
||||
L55
|
||||
L1
|
||||
L99
|
||||
R14
|
||||
L82
|
||||
142
src/day01/mod.rs
Normal file
142
src/day01/mod.rs
Normal file
@@ -0,0 +1,142 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use color_eyre::{
|
||||
Result,
|
||||
eyre::{Error, eyre},
|
||||
};
|
||||
use tracing::{debug, info, instrument};
|
||||
|
||||
const INPUT: &str = include_str!("input/input.txt");
|
||||
|
||||
const LOCK_SIZE: i32 = 100;
|
||||
const LOCK_STARTING_POSITION: i32 = 50;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
impl FromStr for Direction {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
match s {
|
||||
"L" => Ok(Direction::Left),
|
||||
"R" => Ok(Direction::Right),
|
||||
_ => Err(eyre!("Invalid direction")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(input))]
|
||||
fn part1(input: &str) -> Result<i32> {
|
||||
let mut dial = LOCK_STARTING_POSITION;
|
||||
let mut visited_zero_count = 0;
|
||||
for line in input.trim().split('\n') {
|
||||
let dir: &Direction = &line[0..1].parse()?;
|
||||
let clicks: i32 = line[1..].parse()?;
|
||||
match dir {
|
||||
Direction::Left => {
|
||||
debug!("Turn left {} clicks", clicks);
|
||||
dial = (dial - clicks).rem_euclid(LOCK_SIZE);
|
||||
debug!("Dial is now {}", dial);
|
||||
}
|
||||
Direction::Right => {
|
||||
debug!("Turn right {} clicks", clicks);
|
||||
dial = (dial + clicks).rem_euclid(LOCK_SIZE);
|
||||
debug!("Dial is now {}", dial);
|
||||
}
|
||||
}
|
||||
if dial == 0 {
|
||||
visited_zero_count += 1;
|
||||
debug!("Visited zero, count is now {}", visited_zero_count);
|
||||
}
|
||||
}
|
||||
Ok(visited_zero_count)
|
||||
}
|
||||
|
||||
#[instrument(skip(input))]
|
||||
fn part2(input: &str) -> Result<i32> {
|
||||
let mut dial = LOCK_STARTING_POSITION;
|
||||
let mut visited_zero_count = 0;
|
||||
for line in input.trim().split('\n') {
|
||||
let dir: &Direction = &line[0..1].parse()?;
|
||||
let clicks: i32 = line[1..].parse()?;
|
||||
match dir {
|
||||
Direction::Left => {
|
||||
debug!("Turn left {} clicks", clicks);
|
||||
let end = dial - clicks;
|
||||
let passing_zero_count =
|
||||
(dial - 1).div_euclid(LOCK_SIZE) - (end - 1).div_euclid(LOCK_SIZE);
|
||||
if passing_zero_count > 0 {
|
||||
visited_zero_count += passing_zero_count;
|
||||
debug!(
|
||||
"Passed zero {} times, count is now {}",
|
||||
passing_zero_count, visited_zero_count
|
||||
);
|
||||
}
|
||||
dial = end.rem_euclid(LOCK_SIZE);
|
||||
debug!("Dial is now {}", dial);
|
||||
}
|
||||
Direction::Right => {
|
||||
debug!("Turn right {} clicks", clicks);
|
||||
let end = dial + clicks;
|
||||
let passing_zero_count = end.div_euclid(LOCK_SIZE);
|
||||
if passing_zero_count > 0 {
|
||||
visited_zero_count += passing_zero_count;
|
||||
debug!(
|
||||
"Passed zero {} times, count is now {}",
|
||||
passing_zero_count, visited_zero_count
|
||||
);
|
||||
}
|
||||
dial = end.rem_euclid(LOCK_SIZE);
|
||||
debug!("Dial is now {}", dial);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(visited_zero_count)
|
||||
}
|
||||
|
||||
pub fn solve() -> Result<()> {
|
||||
info!("Day 1");
|
||||
{
|
||||
let _span = tracing::info_span!("day01").entered();
|
||||
let p1 = part1(INPUT)?;
|
||||
info!("Part 1: {}", p1);
|
||||
let p2 = part2(INPUT)?;
|
||||
info!("Part 2: {}", p2);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use test_log::test;
|
||||
|
||||
const TEST_INPUT1: &str = include_str!("input/test1.txt");
|
||||
|
||||
#[test]
|
||||
fn test_parse_direction() {
|
||||
let result = "L".parse::<Direction>();
|
||||
assert!(matches!(result.unwrap(), Direction::Left));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_direction() {
|
||||
let result = "U".parse::<Direction>();
|
||||
let err = result.unwrap_err();
|
||||
assert!(err.to_string().contains("Invalid direction"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part1() {
|
||||
assert_eq!(part1(TEST_INPUT1).unwrap(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2() {
|
||||
assert_eq!(part2(TEST_INPUT1).unwrap(), 6);
|
||||
}
|
||||
}
|
||||
29
src/main.rs
Normal file
29
src/main.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
pub mod day01;
|
||||
|
||||
use color_eyre::Result;
|
||||
use tracing::info;
|
||||
use tracing_error::ErrorLayer;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use tracing_subscriber::fmt::format::FmtSpan;
|
||||
use tracing_subscriber::prelude::*;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
color_eyre::install()?;
|
||||
|
||||
tracing_subscriber::registry()
|
||||
.with(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
|
||||
.with(ErrorLayer::default())
|
||||
.with(
|
||||
tracing_subscriber::fmt::layer()
|
||||
.with_line_number(true)
|
||||
.with_span_events(FmtSpan::CLOSE),
|
||||
)
|
||||
.init();
|
||||
|
||||
info!("Advent of Code 2025");
|
||||
{
|
||||
let _span = tracing::info_span!("aoc").entered();
|
||||
day01::solve()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user