-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgalaxies.py
87 lines (64 loc) · 1.99 KB
/
galaxies.py
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
import sys
from itertools import combinations
def expand_universe(starmap:list[list]):
"""Expand the 'universe' on all empty rows & columns that don't contain galaxies"""
newmap = []
for row in starmap:
if '#' not in row:
newmap.append(list(row))
newmap.append(list(row))
adjust = 0
for i in range(len(starmap[0])):
col = [ row[i] for row in starmap ]
if '#' not in col:
for row in newmap:
row.insert(i + adjust, '.')
adjust += 1
return newmap
class Point:
"""Immutable point type.
A tuple would have also been fine in place, this is just for practice"""
def __init__(self, x, y):
if not isinstance(x, int) or not isinstance(y, int):
raise TypeError("Input not an int!")
self.x = x
self.y = y
def __setattr__(self, name, value):
if name in ("x", "y") and name in self.__dict__:
raise ValueError(f"{name} field is immutable!")
super(Point, self).__setattr__(name, value)
def __hash__(self) -> int:
# Cantor Pairing function
return int((self.x + self.y) * (self.x + self.y + 1) / 2 + self.y)
def __eq__(self, other) -> bool:
return self.x == other.x and self.y == other.y
def stepsto(self, other) -> int:
return abs(other.x - self.x) + abs(other.y - self.y)
def __repr__(self) -> str:
return f"({self.x},{self.y})"
def part_one(source):
starmap = [ list(line) for line in source ]
expanded = expand_universe(starmap)
galaxies = []
for y, row in enumerate(expanded):
for x, point in enumerate(row):
if point == '#':
galaxies.append(Point(x, y))
pairs = combinations(galaxies, 2)
sum = 0
for a, b in pairs:
sum += a.stepsto(b)
return sum
if __name__ == "__main__":
if len(sys.argv) <= 1 or sys.argv[1] == '-':
print("Reading from stdin.")
text = [ line for line in sys.stdin ]
else:
try:
print(f"Reading from {sys.argv[1]}.")
with open(sys.argv[1]) as f:
text = [ line for line in sys.stdin ]
except FileNotFoundError:
print(f"File {sys.argv[1]} not found!")
exit()
print(f"Part 1: {part_one(text)}")