summaryrefslogtreecommitdiffstats
path: root/19/py/d24.py
blob: b7479866dafe04c9cebf421f130d952987ab4062 (plain) (blame)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
class hashdict(dict):
    """
    hashable dict implementation, suitable for use as a key into
    other dicts.

        >>> h1 = hashdict({"apples": 1, "bananas":2})
        >>> h2 = hashdict({"bananas": 3, "mangoes": 5})
        >>> h1+h2
        hashdict(apples=1, bananas=3, mangoes=5)
        >>> d1 = {}
        >>> d1[h1] = "salad"
        >>> d1[h1]
        'salad'
        >>> d1[h2]
        Traceback (most recent call last):
        ...
        KeyError: hashdict(bananas=3, mangoes=5)

    based on answers from
       http://stackoverflow.com/questions/1151658/python-hashable-dicts

    """
    def __key(self):
        return tuple(sorted(self.items()))
    def __repr__(self):
        return "{0}({1})".format(self.__class__.__name__,
            ", ".join("{0}={1}".format(
                    str(i[0]),repr(i[1])) for i in self.__key()))

    def __hash__(self):
        return hash(self.__key())
    def __setitem__(self, key, value):
        raise TypeError("{0} does not support item assignment"
                         .format(self.__class__.__name__))
    def __delitem__(self, key):
        raise TypeError("{0} does not support item assignment"
                         .format(self.__class__.__name__))
    def clear(self):
        raise TypeError("{0} does not support item assignment"
                         .format(self.__class__.__name__))
    def pop(self, *args, **kwargs):
        raise TypeError("{0} does not support item assignment"
                         .format(self.__class__.__name__))
    def popitem(self, *args, **kwargs):
        raise TypeError("{0} does not support item assignment"
                         .format(self.__class__.__name__))
    def setdefault(self, *args, **kwargs):
        raise TypeError("{0} does not support item assignment"
                         .format(self.__class__.__name__))
    def update(self, *args, **kwargs):
        raise TypeError("{0} does not support item assignment"
                         .format(self.__class__.__name__))
    # update is not ok because it mutates the object
    # __add__ is ok because it creates a new object
    # while the new object is under construction, it's ok to mutate it
    def __add__(self, right):
        result = hashdict(self)
        dict.update(result, right)
        return result

def inside(p):
    return 0 <= p[0] < 5 and 0 <= p[1] < 5

def neighbours(p):
    return [(p[0]+1, p[1]), (p[0]-1, p[1]), \
            (p[0], p[1]+1), (p[0], p[1]-1)]

def draw(bugs):
    s = ""
    for y in range(5):
        s += "\n"
        for x in range(5):
            if bugs[(x,y)] == True:
                s += "#"
            else:
                s += "."
    return s

def draw_nums(bugs):
    s = ""
    for y in range(5):
        s += "\n"
        for x in range(5):
            s += str(bugs.get((x,y), 0))
    return s

def nums(bugs):
    nums = {}
    for y in range(5):
        for x in range(5):
            p = (x,y)
            if bugs[p] == True:
                for n in neighbours(p):
                    if inside(n):
                        nums[n] = nums.get(n, 0) + 1
    return nums

f = open("../input/24", "r").readlines()

bugs = {}
for y in range(5):
    for x in range(5):
        bugs[(x,y)] = (f[y][x] == "#")

seen = set()
while True:
    h = hashdict(bugs.copy())
    if h in seen:
        break
    seen.add(h)
    new = {}
    ns = nums(bugs)
    for y in range(5):
        for x in range(5):
            p = (x,y)
            n = ns.get(p, 0)
            if bugs[p] == False and (n == 1 or n == 2):
                new[p] = True
            elif bugs[p] == True and n != 1:
                new[p] = False
            else:
                new[p] = bugs[p]
    bugs = new
print(draw(bugs))

ans = 0
for k, v in bugs.items():
    if v == True:
        ans += 2**(k[1]*5 + k[0])
print(ans)