zerosleeps

Since 2010

Advent of Code 2020 day 6

Sunday 6 December 2020

My Python solution for Advent of Code 2020 day 6. My initial working version was much more verbose than the copy below, but the tools used were the same - set and collections.Counter.

Very happy with my decision back during day 3 to split up puzzle input retrieval from parsing - it’s made testing the puzzle examples using the same code paths as testing my actual input much easier, which in turn makes me more likely to actually write those tests.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from collections import Counter
from pathlib import Path
import unittest

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

def parse_raw_input(raw_input):
    return [
            [
                [ char for char in person.strip() ]
            for person in group.splitlines() ]
        for group in raw_input.strip().split('\n\n')
    ]

class Group():
    def __init__(self, input):
        self.people = [person for person in input]

    @property
    def flattened_questions(self):
        return [question for person in self.people for question in person]

    @property
    def unique_questions(self):
        return set(self.flattened_questions)

    @property
    def questions_answered_by_all(self):
        counter = Counter(self.flattened_questions)
        return [question for question, count in counter.items() if count == len(self.people)]

def part_one(parsed_input):
    return sum([len(Group(group).unique_questions) for group in parsed_input])

def part_two(parsed_input):
    return sum([len(Group(group).questions_answered_by_all) for group in parsed_input])

if __name__ == '__main__':
    print(f'Part one: {part_one(parse_raw_input(get_raw_input()))}')
    print(f'Part two: {part_two(parse_raw_input(get_raw_input()))}')

class TestPartOneExamples(unittest.TestCase):
    def test_example_one(self):
        example = """abcx
            abcy
            abcz"""
        self.assertEqual(part_one(parse_raw_input(example)), 6)

    def test_example_two(self):
        example = """abc

            a
            b
            c

            ab
            ac

            a
            a
            a
            a

            b"""
        self.assertEqual(part_one(parse_raw_input(example)), 11)

class TestPartTwoExample(unittest.TestCase):
    def test_example(self):
        example = """abc

            a
            b
            c

            ab
            ac

            a
            a
            a
            a

            b"""
        self.assertEqual(part_two(parse_raw_input(example)), 6)