zerosleeps

Since 2010

Advent of Code 2020 day 5

Back to Python today. I spent as long preparing the input as I did on anything else - for some reason I just can’t grok nested comprehensions in Python. Can write the equivalent nested loops no problem, but when it comes to re-factoring them…

Anyway here it is. Duplication in the row/column functions that could be better. And I’m sure there’s a cleverer way of grabbing multiple consecutive elements in an array for part two, like Ruby’s Enumerable#each_cons.

from pathlib import Path
import unittest

class BoardingPass():
    def __init__(self, input):
        self.input = input

    @property
    def row(self):
        candidates = list(range(128))
        for char in self.input[0:7]:
            if char == 'F':
                candidates = candidates[0:int(len(candidates) / 2)]
            else:
                candidates = candidates[int(len(candidates) / 2):]
        return candidates[0]

    @property
    def column(self):
        candidates = list(range(8))
        for char in self.input[-3:]:
            if char == 'L':
                candidates = candidates[0:int(len(candidates) / 2)]
            else:
                candidates = candidates[int(len(candidates) / 2):]
        return candidates[0]

    @property
    def seat_id(self):
        return ( self.row * 8 ) + self.column

def get_raw_input():
    return (Path(__file__).parent / 'day_05_input.txt').read_text()

def parse_raw_input(raw_input):
    return [ [ char for char in row.strip() ] for row in raw_input.strip().splitlines() ]

def part_one(raw_input):
    seat_ids = [ BoardingPass(parsed_input).seat_id for parsed_input in parse_raw_input(raw_input)]
    return max(seat_ids)

def part_two(raw_input):
    seat_ids = sorted(
        [ BoardingPass(parsed_input).seat_id for parsed_input in parse_raw_input(raw_input)]
    )

    for i, seat_id in enumerate(seat_ids):
        if seat_ids[i + 1] != seat_ids[i] + 1:
            return seat_ids[i] + 1

if __name__ == '__main__':
    print(part_one(get_raw_input()))
    print(part_two(get_raw_input()))

class TestPartOneExamples(unittest.TestCase):
    def test_example_one(self):
        bp = BoardingPass('FBFBBFFRLR')
        self.assertEqual(bp.row, 44)
        self.assertEqual(bp.column, 5)
        self.assertEqual(bp.seat_id, 357)

    def test_example_two(self):
        bp = BoardingPass('BFFFBBFRRR')
        self.assertEqual(bp.row, 70)
        self.assertEqual(bp.column, 7)
        self.assertEqual(bp.seat_id, 567)

    def test_example_three(self):
        bp = BoardingPass('FFFBBBFRRR')
        self.assertEqual(bp.row, 14)
        self.assertEqual(bp.column, 7)
        self.assertEqual(bp.seat_id, 119)

    def test_example_four(self):
        bp = BoardingPass('BBFFBBFRLL')
        self.assertEqual(bp.row, 102)
        self.assertEqual(bp.column, 4)
        self.assertEqual(bp.seat_id, 820)