100 lines
2.4 KiB
Rust
100 lines
2.4 KiB
Rust
#![feature(test, map_first_last, binary_heap_into_iter_sorted)]
|
|
extern crate test;
|
|
use aoc2020::common::*;
|
|
use itertools::Itertools;
|
|
use std::collections::BinaryHeap;
|
|
|
|
const NUM_ROWS: usize = 128;
|
|
const NUM_COLS: usize = 8;
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
struct Position {
|
|
row: usize,
|
|
col: usize,
|
|
}
|
|
|
|
#[inline]
|
|
fn get_position(pass: &str) -> Position {
|
|
Position {
|
|
row: find_spot(&pass[0..7], 'B', NUM_ROWS),
|
|
col: find_spot(&pass[7..], 'R', NUM_COLS),
|
|
}
|
|
}
|
|
|
|
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]
|
|
fn calculate_id(p: &Position) -> usize {
|
|
p.row * 8 + p.col
|
|
}
|
|
|
|
fn collect_ids(s: &str) -> BinaryHeap<usize> {
|
|
s.lines().map(get_position).map(|p| calculate_id(&p)).collect()
|
|
}
|
|
|
|
fn find_missing(ids: BinaryHeap<usize>) -> usize {
|
|
ids.into_iter_sorted().tuple_windows().find(|(a, b)| a - b == 2).unwrap().0 - 1
|
|
}
|
|
|
|
fn main() {
|
|
let ids = collect_ids(&read_input());
|
|
let p1 = ids.peek().unwrap();
|
|
println!("Part 1: {}", p1);
|
|
|
|
let p2 = find_missing(ids);
|
|
println!("Part 2: {}", p2);
|
|
}
|
|
|
|
fn read_input() -> String {
|
|
read_file(5)
|
|
}
|
|
|
|
#[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);
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_part_1(b: &mut test::Bencher) {
|
|
let raw = read_input();
|
|
b.iter(|| assert_eq!(collect_ids(black_box(&raw)).peek(), Some(&913)))
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_part_2(b: &mut test::Bencher) {
|
|
let ids = collect_ids(&read_input());
|
|
b.iter(|| assert_eq!(find_missing(black_box(ids.clone())), 717))
|
|
}
|
|
}
|