advent-of-code/2020/src/bin/day05.rs

105 lines
2.5 KiB
Rust
Raw Normal View History

2020-12-10 12:44:07 +01:00
#![feature(test, map_first_last, binary_heap_into_iter_sorted)]
2020-12-05 09:50:09 +01:00
extern crate test;
2020-12-05 14:41:54 +01:00
use itertools::Itertools;
2020-12-08 14:22:12 +01:00
use std::{collections::BinaryHeap, env};
2020-12-05 09:50:09 +01:00
2020-12-05 10:24:11 +01:00
const NUM_ROWS: usize = 128;
const NUM_COLS: usize = 8;
2020-12-05 14:41:54 +01:00
#[derive(Debug, PartialEq)]
2020-12-05 09:50:09 +01:00
struct Position {
row: usize,
col: usize,
}
2020-12-05 14:41:54 +01:00
#[inline]
2020-12-05 09:50:09 +01:00
fn get_position(pass: &str) -> Position {
2020-12-05 10:24:11 +01:00
Position {
2020-12-05 14:41:54 +01:00
row: find_spot(&pass[0..7], 'B', NUM_ROWS),
col: find_spot(&pass[7..], 'R', NUM_COLS),
2020-12-05 10:24:11 +01:00
}
2020-12-05 09:50:09 +01:00
}
2020-12-05 14:41:54 +01:00
fn find_spot(s: &str, needle: char, max: usize) -> usize {
s.chars()
.zip(1..)
.filter(|(c, _)| *c == needle)
.fold(0, |acc, (_, n)| acc + (max >> n))
}
#[inline]
2020-12-05 09:50:09 +01:00
fn calculate_id(p: &Position) -> usize {
2020-12-05 10:24:11 +01:00
p.row * 8 + p.col
2020-12-05 09:50:09 +01:00
}
2020-12-08 14:22:12 +01:00
fn collect_ids(s: &str) -> BinaryHeap<usize> {
2020-12-05 14:41:54 +01:00
s.lines().map(get_position).map(|p| calculate_id(&p)).collect()
}
2020-12-08 14:22:12 +01:00
fn find_missing(ids: BinaryHeap<usize>) -> usize {
ids.into_iter_sorted().tuple_windows().find(|(a, b)| a - b == 2).unwrap().0 - 1
2020-12-05 14:41:54 +01:00
}
2020-12-05 09:50:09 +01:00
fn main() {
2020-12-05 14:41:54 +01:00
let ids = collect_ids(&read_input());
2020-12-08 14:22:12 +01:00
let p1 = ids.peek().unwrap();
2020-12-05 10:24:11 +01:00
println!("Part 1: {}", p1);
2020-12-08 14:22:12 +01:00
let p2 = find_missing(ids);
2020-12-05 10:24:11 +01:00
println!("Part 2: {}", p2);
2020-12-05 09:50:09 +01:00
}
fn read_input() -> String {
2020-12-10 12:44:07 +01:00
std::fs::read_to_string(
env::args()
.nth(1)
.filter(|n| n != "--bench")
.unwrap_or_else(|| String::from("inputs/day05")),
)
.unwrap()
2020-12-05 09:50:09 +01:00
}
#[cfg(test)]
mod tests {
use super::*;
use test::black_box;
const PASS_1: &str = "BFFFBBFRRR";
const PASS_2: &str = "FFFBBBFRRR";
const PASS_3: &str = "BBFFBBFRLL";
const POS_1: Position = Position { row: 70, col: 7 };
const POS_2: Position = Position { row: 14, col: 7 };
const POS_3: Position = Position { row: 102, col: 4 };
const SID_1: usize = 567;
const SID_2: usize = 119;
const SID_3: usize = 820;
#[test]
fn test_get_position() {
assert_eq!(get_position(PASS_1), POS_1);
assert_eq!(get_position(PASS_2), POS_2);
assert_eq!(get_position(PASS_3), POS_3);
}
#[test]
fn test_calculate_id() {
assert_eq!(calculate_id(&POS_1), SID_1);
assert_eq!(calculate_id(&POS_2), SID_2);
assert_eq!(calculate_id(&POS_3), SID_3);
}
2020-12-05 14:41:54 +01:00
#[bench]
fn bench_part_1(b: &mut test::Bencher) {
let raw = read_input();
2020-12-08 14:22:12 +01:00
b.iter(|| assert_eq!(collect_ids(black_box(&raw)).peek(), Some(&913)))
2020-12-05 14:41:54 +01:00
}
#[bench]
fn bench_part_2(b: &mut test::Bencher) {
let ids = collect_ids(&read_input());
2020-12-08 14:22:12 +01:00
b.iter(|| assert_eq!(find_missing(black_box(ids.clone())), 717))
2020-12-05 14:41:54 +01:00
}
2020-12-05 09:50:09 +01:00
}