From 61125c42a1495ecc92ffef8aa6387b743561dc20 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 15 Dec 2020 09:56:43 +0100 Subject: [PATCH] 2020: day15: part 1 --- aoc2020/benches/bench.rs | 2 + aoc2020/input/day15.txt | 1 + aoc2020/input/day15_provided.txt | 1 + aoc2020/src/day15.rs | 83 ++++++++++++++++++++++++++++++++ aoc2020/src/lib.rs | 1 + aoc2020/src/main.rs | 2 + 6 files changed, 90 insertions(+) create mode 100644 aoc2020/input/day15.txt create mode 100644 aoc2020/input/day15_provided.txt create mode 100644 aoc2020/src/day15.rs diff --git a/aoc2020/benches/bench.rs b/aoc2020/benches/bench.rs index a5447c9..8e13e66 100644 --- a/aoc2020/benches/bench.rs +++ b/aoc2020/benches/bench.rs @@ -14,6 +14,7 @@ use aoc2020::day11; use aoc2020::day12; use aoc2020::day13; use aoc2020::day14; +use aoc2020::day15; fn aoc2020_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -30,6 +31,7 @@ fn aoc2020_all(c: &mut Criterion) { c.bench_function("day12", |b| b.iter(|| day12::run().unwrap())); c.bench_function("day13", |b| b.iter(|| day13::run().unwrap())); c.bench_function("day14", |b| b.iter(|| day14::run().unwrap())); + c.bench_function("day15", |b| b.iter(|| day15::run().unwrap())); } criterion_group! { diff --git a/aoc2020/input/day15.txt b/aoc2020/input/day15.txt new file mode 100644 index 0000000..7102600 --- /dev/null +++ b/aoc2020/input/day15.txt @@ -0,0 +1 @@ +8,11,0,19,1,2 diff --git a/aoc2020/input/day15_provided.txt b/aoc2020/input/day15_provided.txt new file mode 100644 index 0000000..c84ffe7 --- /dev/null +++ b/aoc2020/input/day15_provided.txt @@ -0,0 +1 @@ +0,3,6 diff --git a/aoc2020/src/day15.rs b/aoc2020/src/day15.rs new file mode 100644 index 0000000..6911a49 --- /dev/null +++ b/aoc2020/src/day15.rs @@ -0,0 +1,83 @@ +use std::collections::HashMap; +use std::fmt::Write; + +use anyhow::Result; + +const INPUT: &str = include_str!("../input/day15.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let starting_numbers = input.trim_end() + .split(',') + .map(|num| num.parse().map_err(anyhow::Error::new)) + .collect::>>()?; + + let mut spoken_numbers = HashMap::new(); + let mut next_number: u64 = 0; + let mut turn: usize = 0; + + for num in starting_numbers { + let last_turn = speak_number(num, turn, &mut spoken_numbers); + match last_turn { + Some(prev_turn) => next_number = (turn - prev_turn) as u64, + None => next_number = 0, + } + + turn += 1; + } + + let mut last_number: u64 = 0; + + while turn < 2020 { + // store the number we're about to speak for the solution + last_number = next_number; + + // get the previous time this number was spoken, if any + let last_turn = speak_number(next_number, turn, &mut spoken_numbers); + match last_turn { + // if it was spoken before, the number we'll say next turn is the difference between the + // two turns where it was last spoken + Some(prev_turn) => next_number = (turn - prev_turn) as u64, + // otherwise we'll say 0 next turn + None => next_number = 0, + } + + turn += 1 + } + + Ok(last_number) +} + +/// Inserts the turn a number was spoken in the map. Returns the previous turn the number was +/// spoken, if any +fn speak_number(n: u64, turn: usize, spoken_numbers: &mut HashMap) -> Option { + let res = spoken_numbers.get(&n).copied(); + + spoken_numbers.insert(n, turn); + + res +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day15_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 436); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 447); + } +} diff --git a/aoc2020/src/lib.rs b/aoc2020/src/lib.rs index f4877db..c4cadc0 100644 --- a/aoc2020/src/lib.rs +++ b/aoc2020/src/lib.rs @@ -12,3 +12,4 @@ pub mod day11; pub mod day12; pub mod day13; pub mod day14; +pub mod day15; diff --git a/aoc2020/src/main.rs b/aoc2020/src/main.rs index 104f8af..936890e 100644 --- a/aoc2020/src/main.rs +++ b/aoc2020/src/main.rs @@ -16,6 +16,7 @@ use aoc2020::day11; use aoc2020::day12; use aoc2020::day13; use aoc2020::day14; +use aoc2020::day15; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -33,6 +34,7 @@ fn main() -> Result<()> { day12::run, day13::run, day14::run, + day15::run, ]; aoc::run(days)