From 462918b38272fffb5542c2f4259d7e3237aec696 Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Tue, 10 Dec 2024 21:47:37 -0800 Subject: [PATCH] day11: part 1 solution --- 11/Cargo.lock | 25 ++++++++++++ 11/Cargo.toml | 7 ++++ 11/src/main.rs | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 11/Cargo.lock create mode 100644 11/Cargo.toml create mode 100644 11/src/main.rs diff --git a/11/Cargo.lock b/11/Cargo.lock new file mode 100644 index 0000000..b5abc4f --- /dev/null +++ b/11/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day11" +version = "0.1.0" +dependencies = [ + "itertools", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] diff --git a/11/Cargo.toml b/11/Cargo.toml new file mode 100644 index 0000000..9f1e0f2 --- /dev/null +++ b/11/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day11" +version = "0.1.0" +edition = "2021" + +[dependencies] +itertools = "0.13.0" diff --git a/11/src/main.rs b/11/src/main.rs new file mode 100644 index 0000000..ca5827a --- /dev/null +++ b/11/src/main.rs @@ -0,0 +1,108 @@ +use std::collections::HashMap; +use std::fs::File; +use std::io::{BufRead, BufReader, Lines}; +use std::time::{Duration, Instant}; + +use itertools::Itertools; + +// BOILERPLATE +type InputIter = Lines>; + +pub fn get_input() -> InputIter { + let f = File::open("input").unwrap(); + let br = BufReader::new(f); + br.lines() +} + +fn duration_format(duration: Duration) -> String { + match duration.as_secs_f64() { + x if x > 1.0 => format!("{:.3}s", x), + x if x > 0.010 => format!("{:.3}ms", x * 1e3), + x => format!("{:.3}us", x * 1e6), + } +} + +fn main() { + let input = get_input(); + let start = Instant::now(); + let ans1 = problem1(input); + let duration1 = start.elapsed(); + println!("Problem 1 solution: {} [{}]", ans1, duration_format(duration1)); + + let input = get_input(); + let start = Instant::now(); + let ans2 = problem2(input); + let duration2 = start.elapsed(); + println!("Problem 2 solution: {} [{}]", ans2, duration_format(duration2)); + println!("Total duration: {}", duration_format(duration1 + duration2)); +} + +#[derive(Clone, Copy, Debug, Hash)] +struct Stone { + value: u64, +} + +impl Stone { + fn blink_once(self) -> Vec { + let n_digits = if self.value == 0 { 1 } else { self.value.ilog10() + 1 }; + if self.value == 0 { + vec![Stone { value: 1 }] + } else if n_digits % 2 == 0 { + let parts = ( + self.value / 10u64.pow(n_digits / 2), + self.value % 10u64.pow(n_digits / 2), + ); + vec![Stone { value: parts.0 }, Stone { value: parts.1 }] + } else { + vec![Stone { + value: self.value * 2024, + }] + } + } + fn blink(self, times: usize) -> Vec { + let mut stones = vec![self]; + for _ in 0..times { + stones = stones.iter().flat_map(|stone| stone.blink_once()).collect(); + } + stones + } +} +// PROBLEM 1 solution + +fn problem1(mut input: Lines) -> u64 { + let stones = input + .next() + .unwrap() + .unwrap() + .split_ascii_whitespace() + .map(|v| Stone { + value: v.parse().unwrap(), + }) + .collect_vec(); + stones.iter().flat_map(|stone| stone.blink(25)).count() as u64 +} + +// PROBLEM 2 solution +fn problem2(mut input: Lines) -> u64 { + 0 +} + +#[cfg(test)] +mod tests { + use crate::*; + use std::io::Cursor; + + const EXAMPLE: &str = &"125 17"; + + #[test] + fn problem1_example() { + let c = Cursor::new(EXAMPLE); + assert_eq!(problem1(c.lines()), 55312); + } + + #[test] + fn problem2_example() { + let c = Cursor::new(EXAMPLE); + assert_eq!(problem2(c.lines()), 0); + } +}