aboutsummaryrefslogtreecommitdiffstats
path: root/src/10/solve.py
blob: 780037928069ab56f88d233e5a98a963bed39a55 (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
import sys
sys.path.append("../common")
import aoc

def parse_line(l):
    s = l.split(">")
    vals = list()
    for ss in s:
        if len(ss) == 0:
            continue
        ss = ss.split("<",1)[1]
        vals.append([int(x) for x in ss.split(",")])
    return vals

data = [parse_line(l) for l in aoc.data.split("\n") if len(l) != 0]
posdata = [x[0] for x in data]
veldata = [x[1] for x in data]

def check_adj(pi):
    for p in posdata:
        if abs(p[0] - pi[0]) + abs(p[1] - pi[1]) == 1:
            return True
    return False

def check_data():
    for p in posdata:
        if not check_adj(p):
            return False
    return True

def bounds():
    minx = None
    maxx = None
    miny = None
    maxy = None
    for p in posdata:
        if minx is None or p[0] < minx:
            minx = p[0]
        if maxx is None or p[0] > maxx:
            maxx = p[0]
        if miny is None or p[1] < miny:
            miny = p[1]
        if maxy is None or p[1] > maxy:
            maxy = p[1]
    return minx, maxx, miny, maxy

def solve(part, args):
    count = 0
    distx = None
    disty = None
    while True:
        for i in range(len(data)):
            posdata[i][0] += veldata[i][0]
            posdata[i][1] += veldata[i][1]
        count += 1

        minx, maxx, miny, maxy = bounds()
        if distx == None:
            distx = maxx - minx
            disty = maxy - miny
        else:
            cdistx = maxx - minx
            cdisty = maxy - miny
            if cdistx > distx or cdisty > disty:
                for i in range(len(data)):
                    posdata[i][0] -= veldata[i][0]
                    posdata[i][1] -= veldata[i][1]
                count -= 1
                break
            else:
                distx = cdistx
                disty = cdisty

        if count % 100 == 0:
            aoc.debug("\r" + " " * 50, end="")
            aoc.debug(f"\rcluster size: {distx}, {disty}", end="")

    if part == 1:
        return count
    elif part == 2:
        answer = ""
        minx, maxx, miny, maxy = bounds()
        for y in range(maxy - miny + 1):
            f = lambda x:  "#" if list([x + minx, y + miny]) in posdata else " "
            answer += "".join([f(x) for x in range(maxx - minx + 1)]) + "\n"
        print(repr(answer))
        print(repr(sol2))
        return answer
    else:
        assert(False)

sol2 = """\
#    #  ######  #       #####   #    #  #    #   ####   #    #
#   #   #       #       #    #  #    #  #    #  #    #  #   # 
#  #    #       #       #    #  #    #   #  #   #       #  #  
# #     #       #       #    #  #    #   #  #   #       # #   
##      #####   #       #####   ######    ##    #       ##    
##      #       #       #    #  #    #    ##    #  ###  ##    
# #     #       #       #    #  #    #   #  #   #    #  # #   
#  #    #       #       #    #  #    #   #  #   #    #  #  #  
#   #   #       #       #    #  #    #  #    #  #   ##  #   # 
#    #  #       ######  #####   #    #  #    #   ### #  #    #
"""

aoc.run(lambda args: solve(1, args), lambda args: solve(2, args), sols=[10659, sol2])