1+ #!/usr/bin/env python
2+ # -*- coding: utf-8 -*-
3+
4+ from heapq import heappop , heappush
5+
6+ def parse (data ):
7+ points = []
8+ for point in data .split ('\n ' ):
9+ x , y = point .split (',' )
10+ points .append ((int (x ), int (y )))
11+
12+ return points
13+
14+ split_data = parse
15+ completed = True
16+ raw_data = None # Not To be touched
17+
18+ def part1 (data ):
19+ movements = [(0 , - 1 ), (0 , 1 ), (1 , 0 ), (- 1 , 0 )]
20+ mapSize = 71
21+ goal = (70 ,70 )
22+ corrupted = data [:1024 ]
23+
24+
25+ seen = set ()
26+ queue = [(0 ,0 ,0 , [(0 ,0 )])]
27+ while len (queue ) > 0 :
28+ x , y , steps , path = queue .pop (0 )
29+
30+ for dx , dy in movements :
31+ nx , ny = x + dx , y + dy
32+ if not (0 <= nx < mapSize and 0 <= ny < mapSize ): continue
33+ if (nx , ny ) in seen : continue
34+ if (nx , ny ) in corrupted : continue
35+ if (nx , ny ) == goal :
36+ # plot(path+[goal], corrupted, mapSize)
37+ return steps + 1
38+
39+ seen .add ((nx , ny ))
40+ queue .append ((nx , ny , steps + 1 , path + [(nx , ny )]))
41+
42+ print (seen )
43+ print (f"WTF? We saw { len (seen )} locations and still haven't seen the goal!" )
44+
45+ def plot (path , walls , size ):
46+ for y in range (size ):
47+ for x in range (size ):
48+ if (x , y ) in walls :
49+ print ('#' , end = '' )
50+ elif (x , y ) in path :
51+ print ('O' , end = '' )
52+ else :
53+ print ('.' , end = '' )
54+ print ()
55+
56+ def hasPath (start , end , blocked , bounds ):
57+ # Since we don't care much about optimality, this we will implement the A* algorithm
58+ movements = [(0 , - 1 ), (0 , 1 ), (1 , 0 ), (- 1 , 0 )]
59+ (sx , sy ), (ex , ey ) = start , end
60+
61+ seen = set ()
62+ queue = [(abs (ex - sx )+ abs (ey - sy ), sx , sy , id (0 ), [sx , sy ])] # Heuristic, x, y, unique, path
63+ while len (queue ) > 0 :
64+ _ , x , y , _ , path = heappop (queue )
65+
66+ for dx , dy in movements :
67+ nx , ny = x + dx , y + dy
68+ if not (0 <= nx < bounds [0 ] and 0 <= ny < bounds [1 ]): continue
69+ if (nx , ny ) in seen : continue
70+ if (nx , ny ) in blocked : continue
71+ if (nx , ny ) == end : return path + [end ]
72+
73+ seen .add ((nx , ny ))
74+ heappush (queue , (abs (ex - nx )+ abs (ey - ny ), nx , ny , id (0 ), path + [(nx , ny )]))
75+
76+ return False
77+
78+ def part2 (data ):
79+ checking = 1024
80+ path = hasPath ((0 , 0 ), (70 , 70 ), data [:checking ], (71 , 71 ))
81+ while True :
82+ checking += 1
83+ if data [checking - 1 ] in path : # Only update if the current byte disturbs the precalculated path (optimization)
84+ path = hasPath ((0 , 0 ), (70 , 70 ), data [:checking ], (71 , 71 ))
85+ if path == False :
86+ # plot(hasPath((0, 0), (70, 70), data[:checking-1], (71, 71)), data[:checking], 71)
87+ break
88+ # plot(path, data[:checking], 71)
89+ # print('---')
90+
91+ # if checking % 100 == 0: print(f'{checking/len(data):,.2%}')
92+
93+ return f'{ data [checking - 1 ][0 ]} ,{ data [checking - 1 ][1 ]} '
0 commit comments