Opportunity of code 2020 – boarding seat issues
Advent of code 2020 – Binary Boarding
This question is about using 10 byte characters to represent boarding seats. Aircraft seats have 128 rows and 8 columns. For example, "fbbffrlr" indicates that the position is in row 44 and column 5.
-
B and F are used to represent the number of rows;
F: Indicates the first half, such as 0-127, then the first f indicates that the position is in the range of 0-63;
B: Indicates the latter half, such as 0-63, then the second B indicates that the position is in the range of 32-63;
...
Thus, the number of lines is 44 -
R and L are used to represent the number of columns;
R: Indicates the latter half;
50: Represents the first half;
...
Thus, the number of columns is 5
Structure defining location
Because the number of rows and columns does not exceed 255, the number of rows and columns can be expressed as 8bit integers, u8 in Rust.
#[derive(Default, Debug, PartialEq)] struct Seat { row: u8, col: u8, }
Resolution location
We know that the binary representation of 127 is 7 1s;
127 0111 1111
Then, F and B of the first seven characters can represent 0 or 1 on the seven bit bits in order, f represents 0 and B represents 1;
FBFBBFF 0101100 Representative 44
Similarly, R and L of the last three characters can be used to represent 0 or 1 on the three bit bits in order, L represents 0 and R represents 1;
RLR 101 Representative 5
It can be used in Rust bitvec The library is easy to operate.
You can import with the command
cargo add bitvec
Define location resolution method:
use bitvec::prelude::*; impl Seat { const ROW_BITS: usize = 7; const COL_BITS: usize = 3; fn parse(input: &str) -> Self { let bytes = input.as_bytes(); let mut res: Seat = Default::default(); { let row = BitSlice::<Msb0, _>::from_element_mut(&mut res.row); for (i, &b) in bytes[0..Self::ROW_BITS].iter().enumerate() { row.set( (8 - Self::ROW_BITS) + i, match b { b'F' => false, b'B' => true, _ => panic!("unexpected row letter : {}", b as char), }, ); } } { let col = BitSlice::<Msb0, _>::from_element_mut(&mut res.col); for (i, &b) in bytes[Self::ROW_BITS..][..Self::COL_BITS].iter().enumerate() { col.set( (8 - Self::COL_BITS) + i, match b { b'L' => false, b'R' => true, _ => panic!("unexpected col letter : {}", b as char), }, ); } } res } }
Test location resolution method:
#[test] fn test_parse() { let input = "FBFBBFFRLR"; let seat = Seat::parse(input); assert_eq!(seat, Seat { row: 44, col: 5 }); }
Position number from position
We define the data deconstruction Seat of location, which is represented by row and col.
The position number can be expressed as:
id = row * 8 + col
Position number calculation function:
impl Seat { const ROW_BITS: usize = 7; const COL_BITS: usize = 3; fn id(&self) -> u64 { // Instead of multiplying the number of rows by 8 by a shift operation ((self.row as u64) << Self::COL_BITS) + (self.col as u64) } }
Test:
#[test] fn test_seat_id() { macro_rules! validate { ($input: expr, $row: expr, $col: expr, $id: expr) => { let seat = Seat::parse($input); assert_eq!( seat, Seat { row: $row, col: $col } ); assert_eq!(seat.id(), $id); }; } validate!("BFFFBBFRRR", 70, 7, 567); validate!("FFFBBBFRRR", 14, 7, 119); validate!("BBFFBBFRLL", 102, 4, 820); }
Question 1: calculate the maximum location number in the test set
fn main() { let max_id = itertools::max( include_str!("input.txt") .lines() .map(Seat::parse) .map(|seat| seat.id()), ); println!("The maximum seat ID is {:?}", max_id); }
Question 2: find the missing location number
last_id, i.e. discontinuous Id, for example, an 8 is vacant between 7 and 9
Find last_id, we need to calculate all the location numbers and sort them. We store all the location numbers in Vec. To implement the sort() method, we need to implement partialord, ord trail for the Seat data structure
Change Seat data structure
#[derive(Clone, Copy,Default, Debug, PartialEq, PartialOrd, Eq, Ord)] struct Seat { row: u8, col: u8, }
fn main() { let mut ids: Vec<_> = include_str!("input.txt").lines().map(Seat::parse).collect(); ids.sort(); let mut last_id: Option<Seat> = None; for id in ids { if let Some(last_id) = last_id { let gap = id.id() - last_id.id(); if gap > 1{ println!("Our seat ID is {}", last_id.id()); return; } } last_id = Some(id); } }
Reference learning: https://fasterthanli.me/series/advent-of-code-2020/part-5