diff --git a/data/input-10.txt b/data/input-10.txt new file mode 100644 index 0000000..a97393a --- /dev/null +++ b/data/input-10.txt @@ -0,0 +1,101 @@ +144 +10 +75 +3 +36 +80 +143 +59 +111 +133 +1 +112 +23 +62 +101 +137 +41 +24 +8 +121 +35 +105 +161 +69 +52 +21 +55 +29 +135 +142 +38 +108 +141 +115 +68 +7 +98 +82 +9 +72 +118 +27 +153 +140 +61 +90 +158 +102 +28 +134 +91 +2 +17 +81 +31 +15 +120 +20 +34 +56 +4 +44 +74 +14 +147 +11 +49 +128 +16 +99 +66 +47 +125 +155 +130 +37 +67 +54 +60 +48 +136 +89 +119 +154 +122 +129 +163 +73 +100 +85 +95 +30 +76 +162 +22 +79 +88 +150 +53 +63 +92 diff --git a/data/output-10.txt b/data/output-10.txt new file mode 100644 index 0000000..bfe4ff3 --- /dev/null +++ b/data/output-10.txt @@ -0,0 +1,2 @@ +2240 +99214346656768 diff --git a/src/day10.rs b/src/day10.rs new file mode 100644 index 0000000..cbd3f49 --- /dev/null +++ b/src/day10.rs @@ -0,0 +1,72 @@ +// ==== day 10 + +use crate::utils; +use anyhow::Result; + +pub fn count_diff1_diff3(diffs: &Vec) -> usize { + let diff_1 = diffs.iter().filter(|n| **n == 1).count(); + let diff_3 = diffs.iter().filter(|n| **n == 3).count(); + diff_1 * diff_3 +} + +// the number of paths from a contiguous sequence [i+0, i+1, i+N-1] of size N +// follows the pattern 0, 1, 1, 2, 4, where the total paths for a runlength N +// is sum of the paths in N-3, N-2, and N-1. +fn paths_by_runlength(runlength: usize) -> usize { + let mut p: Vec = vec![0, 1, 1]; // vec of most recent 4 in sequence + const L: usize = 3; // length of p Vec + for i in L..runlength + 1 { + p[i % L] = p[(i - 3) % L] + p[(i - 2) % L] + p[(i - 1) % L]; + } + p[runlength % L] +} + +fn count_paths(diffs: &Vec) -> usize { + // count the runs of 1s + let mut last_diff: i64 = 0; + let mut runlength: usize = 1; + let mut runs_of_ones: Vec = Vec::new(); + diffs.iter().for_each(|d| { + if *d == last_diff { + runlength += 1; + } else { + if last_diff == 1 { + runs_of_ones.push(runlength + 1); + } + runlength = 1; + last_diff = *d; + } + }); + + // figure out how many path options we have for each run and multiply + runs_of_ones + .iter() + .map(|r| paths_by_runlength(*r)) + .product() +} + +pub fn run() -> Result<(usize, usize)> { + let mut data = utils::read_i64s("data/input-10.txt")?; + let answers = utils::read_i64s("data/output-10.txt")?; + + // add the adapters on either end of the sequence and sort + let max = data.iter().max().unwrap().clone(); + data.push(0); // add the (0) adapter at my seat + data.push(max + 3); // add the (max in the list + 3) adapter in my device + data.sort_unstable(); // paths are always sorted + + // create a vec of the diffs from data[i] to data[i+1] + let diffs: Vec = data + .iter() + .enumerate() + .take(data.len() - 1) + .map(|(i, _)| (&data[i] - &data[i + 1]).abs()) + .collect(); + + let p1 = count_diff1_diff3(&diffs); + let p2 = count_paths(&diffs); + + assert_eq!(p1, answers[0] as usize); + assert_eq!(p2, answers[1] as usize); + Ok((p1, p2)) +} diff --git a/src/main.rs b/src/main.rs index 5505809..4974ce6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod day06; mod day07; mod day08; mod day09; +mod day10; mod utils; // TODO @@ -31,5 +32,6 @@ fn main() -> Result<()> { println!("Day 07: {:?}", day07::run()?); println!("Day 08: {:?}", day08::run()?); println!("Day 09: {:?}", day09::run()?); + println!("Day 10: {:?}", day10::run()?); Ok(()) }