use std::fs; type SeatCode = [char; 10]; fn main() -> Result<(), Box<dyn std::error::Error>> { let input = fs::read_to_string("input")?; // Part 1 let max_id: Result<usize, String> = input .lines() .map(|code| { let (row, col) = find_seat(parse_seatcode(code)?); Ok(row * 8 + col) }) .max() .ok_or("No seat codes set")?; println!("{}", max_id?); // Part 2 let mut ids = input .lines() .map(|code| { let (row, col) = find_seat(parse_seatcode(code)?); Ok(row * 8 + col) }) .collect::<Result<Vec<usize>, String>>()?; ids.sort(); let mut previous = ids[0]; for id in &ids[1..] { if id - 1 != previous { println!("{}", id); break; } else { previous = *id; } } Ok(()) } fn parse_seatcode(input: &str) -> Result<SeatCode, String> { let mut output = ['0'; 10]; for (i, c) in input.chars().enumerate() { if i > 10 { Err(format!("Seat code too long: '{}'", input))?; } if !['F', 'B', 'L', 'R'].iter().any(|valid| &c != valid) { Err(format!("Invalid character in seat code: '{}'", input))?; } output[i] = c; } Ok(output) } fn find_seat(code: SeatCode) -> (usize, usize) { let midpoint = |(start, end): (usize, usize)| (start + end) / 2; let binary_follow = |range: (usize, usize), direction: &char| match direction { 'F' | 'L' => (range.0, midpoint(range)), 'B' | 'R' => (midpoint(range) + 1, range.1), _ => unreachable!("We already checked all characters are valid"), }; let row = code[..7].iter().fold((0, 127), binary_follow).0; let col = code[7..].iter().fold((0, 7), binary_follow).0; (row, col) } #[cfg(test)] mod tests { use super::*; #[test] fn test_simple() -> Result<(), Box<dyn std::error::Error>> { let input = "FBFBBFFRLR"; let seat = find_seat(parse_seatcode(input)?); assert_eq!(seat, (44, 5)); Ok(()) } #[test] fn test_simple2() -> Result<(), Box<dyn std::error::Error>> { let input = "BFFFBBFRRR"; let seat = find_seat(parse_seatcode(input)?); assert_eq!(seat, (70, 7)); Ok(()) } #[test] fn test_simple3() -> Result<(), Box<dyn std::error::Error>> { let input = "FFFBBBFRRR"; let seat = find_seat(parse_seatcode(input)?); assert_eq!(seat, (14, 7)); Ok(()) } #[test] fn test_simple4() -> Result<(), Box<dyn std::error::Error>> { let input = "BBFFBBFRLL"; let seat = find_seat(parse_seatcode(input)?); assert_eq!(seat, (102, 4)); Ok(()) } }