summaryrefslogtreecommitdiffstats
path: root/src/bin/2020/day5.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/2020/day5.rs')
-rw-r--r--src/bin/2020/day5.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/bin/2020/day5.rs b/src/bin/2020/day5.rs
new file mode 100644
index 0000000..abfd400
--- /dev/null
+++ b/src/bin/2020/day5.rs
@@ -0,0 +1,96 @@
+use advent_of_code::prelude::*;
+
+pub fn parse(fh: File) -> Result<impl Iterator<Item = u64>> {
+ Ok(parse::raw_lines(fh).map(|line| seat_id(&line).unwrap()))
+}
+
+pub fn part1(ids: impl Iterator<Item = u64>) -> Result<u64> {
+ let mut max = 0;
+ for id in ids {
+ if id > max {
+ max = id;
+ }
+ }
+ Ok(max)
+}
+
+pub fn part2(ids: impl Iterator<Item = u64>) -> Result<u64> {
+ let mut seats = vec![false; 1024];
+ for id in ids {
+ seats[id as usize] = true;
+ }
+ let first = seats
+ .iter()
+ .position(|b| *b)
+ .context("failed to find taken seat")?;
+ let seat = seats
+ .iter()
+ .skip(first)
+ .position(|b| !*b)
+ .context("failed to find free seat")?
+ + first;
+ if !seats[seat - 1] || seats[seat] || !seats[seat + 1] {
+ return Err(anyhow!("invalid seat found"));
+ }
+ Ok(seat.try_into()?)
+}
+
+fn seat_id(desc: &str) -> Result<u64> {
+ if desc.len() != 10 {
+ return Err(anyhow!("invalid desc {}", desc));
+ }
+ let row_desc = &desc[0..7];
+ let col_desc = &desc[7..10];
+
+ let mut min_row = 0;
+ let mut max_row = 127;
+ for c in row_desc.chars() {
+ let mid = (max_row + min_row) / 2;
+ match c {
+ 'F' => {
+ max_row = mid;
+ }
+ 'B' => {
+ min_row = mid + 1;
+ }
+ _ => return Err(anyhow!("invalid desc {}", desc)),
+ }
+ }
+ if min_row != max_row {
+ return Err(anyhow!("bug"));
+ }
+ let row = min_row;
+
+ let mut min_col = 0;
+ let mut max_col = 7;
+ for c in col_desc.chars() {
+ let mid = (max_col + min_col) / 2;
+ match c {
+ 'L' => {
+ max_col = mid;
+ }
+ 'R' => {
+ min_col = mid + 1;
+ }
+ _ => return Err(anyhow!("invalid desc {}", desc)),
+ }
+ }
+ if min_col != max_col {
+ return Err(anyhow!("bug"));
+ }
+ let col = min_col;
+
+ Ok(row * 8 + col)
+}
+
+#[test]
+fn test() {
+ assert_eq!(
+ part1(parse(parse::data(2020, 5).unwrap()).unwrap()).unwrap(),
+ 978
+ );
+ assert_eq!(
+ part2(parse(parse::data(2020, 5).unwrap()).unwrap()).unwrap(),
+ 727
+ );
+}