1
1
from collections import namedtuple
2
2
from dataclasses import dataclass
3
+ from typing import Literal , LiteralString , List
4
+
5
+
6
+ @dataclass
7
+ class Coordinate :
8
+ x : int
9
+ y : int
10
+
11
+
12
+ Grid = list [list [str | Coordinate ]]
3
13
4
- Grid = list [list [str ]]
5
14
6
15
def load_file (file_path : str ) -> Grid :
7
16
with open (file_path ) as file :
8
17
return [list (i .strip ()) for i in file ]
9
18
10
- def row_is_empty (grid : Grid , row : int ) -> bool :
11
- return all (cell == "." for cell in grid [row ])
12
19
13
20
def column_is_empty (grid : Grid , column : int ) -> bool :
14
21
return all (row [column ] == "." for row in grid )
15
22
16
- def expand_grid_rows (grid : Grid ) -> Grid :
17
- new_grid :Grid = []
18
- for idx , row in enumerate (grid ):
19
- new_grid .append (row )
20
- if row_is_empty (grid ,idx ):
21
- for i in range (1_000_000 ): # Part 2 Don't do this...
22
- new_grid .append (row )
23
- return new_grid
24
23
25
- def expand (grid : Grid ) -> Grid :
26
- return transpose (expand_grid_rows (transpose (expand_grid_rows (grid ))))
24
+ def offset_all_in_column (grid : Grid , column : int , offset : int ,
25
+ coordinate_to_adjust : Literal ["x" ] | Literal ["y" ]) -> None :
26
+ for row in grid :
27
+ if isinstance (row [column ], Coordinate ):
28
+ if coordinate_to_adjust == "x" :
29
+ row [column ].x += offset
30
+ else :
31
+ row [column ].y += offset
27
32
28
33
29
- def transpose (grid : Grid ) -> Grid :
30
- return [list (x ) for x in list (zip (* grid ))]
34
+ def offset_all_in_row (grid : Grid , row : int , offset : int , coordinate_to_adjust : Literal ["x" ] | Literal ["y" ]) -> None :
35
+ for x in grid [row ]:
36
+ if isinstance (x , Coordinate ):
37
+ if coordinate_to_adjust == "x" :
38
+ x .x += offset
39
+ else :
40
+ x .y += offset
31
41
32
- namedtuple ("Test" ,["x" ,"y" ])
33
42
34
- @dataclass (frozen = True )
35
- class Coordinate :
36
- x : int
37
- y : int
43
+ def adjust_coordinates (grid : Grid , coordinate_to_adjust : Literal ["x" ] | Literal ["y" ]) -> None :
44
+ current_offset = 0
45
+ for idx , row in enumerate (grid ):
46
+ if column_is_empty (grid , idx ):
47
+ current_offset += 1_000_000 - 1
48
+ else :
49
+ offset_all_in_column (grid , idx , current_offset , coordinate_to_adjust )
50
+
51
+
52
+ def expand (grid : Grid ) -> None :
53
+ adjust_coordinates (grid , 'x' )
54
+ grid = transpose (grid )
55
+ adjust_coordinates (grid , 'y' )
56
+
38
57
39
58
def find_galaxies (grid : Grid ) -> list [Coordinate ]:
40
59
coords = []
41
60
for row in range (len (grid )):
42
61
for column in range (len (grid [0 ])):
43
62
if grid [row ][column ] == "#" :
44
- coords .append (Coordinate (column ,row ))
63
+ new_coord = Coordinate (column , row )
64
+ grid [row ][column ] = new_coord
65
+ coords .append (new_coord )
45
66
return coords
46
67
68
+
69
+ def transpose (grid : Grid ) -> Grid :
70
+ return [list (x ) for x in list (zip (* grid ))]
71
+
72
+
47
73
def distance (coord1 : Coordinate , coord2 : Coordinate ) -> int :
48
74
return abs (coord1 .x - coord2 .x ) + abs (coord1 .y - coord2 .y )
49
75
76
+
50
77
def all_pairs (coords : list [Coordinate ]) -> int :
51
78
total = 0
52
79
for i in range (len (coords )):
53
80
for j in range (i ):
54
- total += distance (coords [i ],coords [j ])
81
+ total += distance (coords [i ], coords [j ])
55
82
return total
56
83
57
84
58
85
def main ():
59
86
grid = load_file ("../input" )
60
- expanded = expand (grid )
61
- galaxies = find_galaxies ( expanded )
87
+ galaxies = find_galaxies (grid )
88
+ expand ( grid )
62
89
result = all_pairs (galaxies )
63
90
print (result )
64
91
print ("Hello, World!" )
65
92
93
+
66
94
if __name__ == "__main__" :
67
95
main ()
68
-
69
-
70
- ## Part 2
71
- """
72
- Find original coordinates first (before any expansion)
73
- Scan the galaxy horizontally, keep track of how many blank columns, add that to the coordinate
74
- Transpose, do again.
75
- """
0 commit comments