use crate::prelude::*; pub fn solution() -> Solution { Solution::new(Day::new(5, 2020), part_1, part_2).with_expected(850, 599) } const MAX_ROW_RANGE: i32 = 128; const MAX_COLUMN_RANGE: i32 = 8; fn calculate_row_and_column(input: &str) -> (i32, i32) { let mut row_range = 0..MAX_ROW_RANGE; let mut column_range = 0..MAX_COLUMN_RANGE; for character in input.chars() { let row_min = row_range.start; let row_max = row_range.end; let row_difference = (row_max - row_min) / 2; let column_min = column_range.start; let column_max = column_range.end; let column_difference = (column_max - column_min) / 2; match character { 'F' => { row_range = row_min..(row_max - row_difference); } 'B' => { row_range = (row_min + row_difference)..row_max; } 'L' => { column_range = column_min..(column_max - column_difference); } 'R' => { column_range = (column_min + column_difference)..column_max; } _ => unreachable!("{character}"), } } (row_range.start, column_range.start) } fn calculate_seat_id((row, column): (i32, i32)) -> i32 { (row * 8) + column } fn part_1(input: &str) -> Result { Ok( input .lines() .map(calculate_row_and_column) .map(calculate_seat_id) .max() .unwrap() .to_string(), ) } fn part_2(input: &str) -> Result { let seat_ids = input .lines() .map(calculate_row_and_column) .map(calculate_seat_id) .collect::>(); let max_seat_id = seat_ids.iter().max().unwrap(); let min_seat_id = seat_ids.iter().min().unwrap(); Ok( (*min_seat_id..*max_seat_id) .find(|index| !seat_ids.contains(index)) .map(|id| id.to_string()) .unwrap(), ) }