Opportunity of code 2020 -- boarding seat problem

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

Tags: Back-end Rust

Posted on Sat, 06 Nov 2021 21:46:34 -0400 by cdm2