use std::convert::TryFrom;

fn find_seat<I: Iterator<Item = char>>(source: &mut I) -> (u8, u8) {
    let mut row = 0;
    let mut col = 0;
    for c in source {
        match c {
            'F' => {
                row *= 2;
            }
            'B' => {
                row = row * 2 + 1;
            }
            'L' => {
                col *= 2;
            }
            'R' => {
                col = col * 2 + 1;
            }
            _ => (),
        }
    }
    (row, col)
}

fn seat_id(row: u8, col: u8) -> u16 {
    u16::from(row) * 8 + u16::from(col)
}

fn max_seat<I: Iterator<Item = u16>>(ids: &mut I) -> u16 {
    ids.max().unwrap()
}

fn my_seat<I: Iterator<Item = u16>>(ids: &mut I) -> u16 {
    let mut filled: Vec<bool> = Vec::with_capacity(1024);
    filled.resize(1024, false);
    for seat in ids {
        filled[usize::from(seat)] = true;
    }
    for (i, f) in filled.iter().enumerate() {
        if !f && i < 1023 && i > 0 && filled[i + 1] && filled[i - 1] {
            return u16::try_from(i).unwrap();
        }
    }
    panic!("not found")
}

fn main() {
    use std::env;
    use std::io::BufRead;
    let args: Vec<_> = env::args().collect();
    let lines = std::io::BufReader::new(std::fs::File::open(&args[1]).unwrap()).lines();
    let mut seats = lines.map(|l| {
        let (row, col) = find_seat(&mut l.unwrap().chars());
        seat_id(row, col)
    });
    println!(
        "{}",
        match args[2].as_ref() {
            "1" => max_seat(&mut seats),
            "2" => my_seat(&mut seats),
            _ => panic!("unknown problem"),
        }
    );
}