AoC day 5: Binary Boarding

advent of code aoc2020 haskell

The trick today is to squint and see binary coding for what it is, and decode it as such instead of getting lost in implementation. This post is literate Haskell, and one of the rare where there is no header of imports and extensions.

Seats are numbered from front to back, then left to right,1 so the decoding for instructions is as follows.

toBit :: Char -> Int
toBit 'F' = 0
toBit 'B' = 1
toBit 'L' = 0
toBit 'R' = 1

I can then combine them all to a single seat number.

passToSeat :: String -> Int
passToSeat = foldl1 (\a b -> 2*a + b) . map toBit

And apply it to all tickets in input to find the maximum.

main = do
  passes <- lines <$> readFile ""
  let seatIds = map passToSeat passes
  print $ maximum seatIds

For part 2, the most reliable way to proceed without doing it by hand is to simply transcribe the statement: I’m looking for a seat number that’s missing with its two neighbors2 being present.

  let seatRange = [minimum seatIds..maximum seatIds]
  print $ filter (\s -> s + 1 `elem` seatIds
                        && s - 1 `elem` seatIds
                        && s `notElem` seatIds) seatRange

This concludes today’s solution. See you soon!

  1. Had they been ordered right to left instead, the seat order would have been the exact reverse of the lexicographical ASCII order. Missed opportunity!↩︎

  2. Of course they’re not really neighbors if they span across rows.↩︎