2020: day15: part 1
This commit is contained in:
parent
c1b14d8768
commit
61125c42a1
|
@ -14,6 +14,7 @@ use aoc2020::day11;
|
||||||
use aoc2020::day12;
|
use aoc2020::day12;
|
||||||
use aoc2020::day13;
|
use aoc2020::day13;
|
||||||
use aoc2020::day14;
|
use aoc2020::day14;
|
||||||
|
use aoc2020::day15;
|
||||||
|
|
||||||
fn aoc2020_all(c: &mut Criterion) {
|
fn aoc2020_all(c: &mut Criterion) {
|
||||||
c.bench_function("day01", |b| b.iter(|| day01::run().unwrap()));
|
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("day12", |b| b.iter(|| day12::run().unwrap()));
|
||||||
c.bench_function("day13", |b| b.iter(|| day13::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("day14", |b| b.iter(|| day14::run().unwrap()));
|
||||||
|
c.bench_function("day15", |b| b.iter(|| day15::run().unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
criterion_group! {
|
criterion_group! {
|
||||||
|
|
1
aoc2020/input/day15.txt
Normal file
1
aoc2020/input/day15.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
8,11,0,19,1,2
|
1
aoc2020/input/day15_provided.txt
Normal file
1
aoc2020/input/day15_provided.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
0,3,6
|
83
aoc2020/src/day15.rs
Normal file
83
aoc2020/src/day15.rs
Normal file
|
@ -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<String> {
|
||||||
|
let mut res = String::with_capacity(128);
|
||||||
|
|
||||||
|
writeln!(res, "part 1: {}", part1(INPUT)?)?;
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> Result<u64> {
|
||||||
|
let starting_numbers = input.trim_end()
|
||||||
|
.split(',')
|
||||||
|
.map(|num| num.parse().map_err(anyhow::Error::new))
|
||||||
|
.collect::<Result<Vec<u64>>>()?;
|
||||||
|
|
||||||
|
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<u64, usize>) -> Option<usize> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,3 +12,4 @@ pub mod day11;
|
||||||
pub mod day12;
|
pub mod day12;
|
||||||
pub mod day13;
|
pub mod day13;
|
||||||
pub mod day14;
|
pub mod day14;
|
||||||
|
pub mod day15;
|
||||||
|
|
|
@ -16,6 +16,7 @@ use aoc2020::day11;
|
||||||
use aoc2020::day12;
|
use aoc2020::day12;
|
||||||
use aoc2020::day13;
|
use aoc2020::day13;
|
||||||
use aoc2020::day14;
|
use aoc2020::day14;
|
||||||
|
use aoc2020::day15;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let days: &[DayFunc] = &[
|
let days: &[DayFunc] = &[
|
||||||
|
@ -33,6 +34,7 @@ fn main() -> Result<()> {
|
||||||
day12::run,
|
day12::run,
|
||||||
day13::run,
|
day13::run,
|
||||||
day14::run,
|
day14::run,
|
||||||
|
day15::run,
|
||||||
];
|
];
|
||||||
|
|
||||||
aoc::run(days)
|
aoc::run(days)
|
||||||
|
|
Loading…
Reference in a new issue