-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path14-2.py
executable file
·133 lines (115 loc) · 3.78 KB
/
14-2.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
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
131
132
133
#!/usr/bin/env python
import numpy
class Dish:
def __init__(self, lines):
self.height = len(lines)
self.width = len(lines[0])
self.map = numpy.zeros((self.height, self.width), dtype=numpy.uint8)
for y in range(self.height):
for x in range(self.width):
if lines[y][x] == 'O':
self.map[y, x] = 1
elif lines[y][x] == '#':
self.map[y, x] = 2
def load(self):
load = 0
for y in range(self.height):
for x in range(self.width):
if self.map[y, x] == 1:
load += self.height - y
return load
def move_north(self, start_y, x):
end_y = start_y
for check_y in range((start_y - 1), -1, -1):
if self.map[check_y, x] != 0:
break
end_y = check_y
self.map[start_y, x] = 0
self.map[end_y, x] = 1
return end_y
def move_south(self, start_y, x):
end_y = start_y
for check_y in range((start_y + 1), self.height):
if self.map[check_y, x] != 0:
break
end_y = check_y
self.map[start_y, x] = 0
self.map[end_y, x] = 1
return end_y
def move_west(self, y, start_x):
end_x = start_x
for check_x in range((start_x - 1), -1, -1):
if self.map[y, check_x] != 0:
break
end_x = check_x
self.map[y, start_x] = 0
self.map[y, end_x] = 1
return end_x
def move_east(self, y, start_x):
end_x = start_x
for check_x in range((start_x + 1), self.width):
if self.map[y, check_x] != 0:
break
end_x = check_x
self.map[y, start_x] = 0
self.map[y, end_x] = 1
return end_x
def tilt_north(self):
for y in range(self.height):
for x in range(self.width):
if self.map[y, x] == 1:
self.move_north(y, x)
def tilt_south(self):
for y in range((self.height - 1), -1, -1):
for x in range(self.width):
if self.map[y, x] == 1:
self.move_south(y, x)
def tilt_west(self):
for y in range(self.height):
for x in range(self.width):
if self.map[y, x] == 1:
self.move_west(y, x)
def tilt_east(self):
for y in range(self.height):
for x in range((self.width - 1), -1, -1):
if self.map[y, x] == 1:
self.move_east(y, x)
def cycle(self):
self.tilt_north()
self.tilt_west()
self.tilt_south()
self.tilt_east()
def spin(self):
seen = []
num_cycles = 0
cycle_length = 0
while True:
seen.append(numpy.copy(self.map))
self.cycle()
num_cycles += 1
matches = [numpy.array_equal(c, self.map) for c in seen]
if any(matches):
cycle_length = num_cycles - matches.index(True)
break
skip_cycles = (1_000_000_000 - num_cycles) // cycle_length
remainder = (1_000_000_000 - num_cycles) % cycle_length
for _ in range(remainder):
self.cycle()
def __str__(self):
s = f"<{self.__class__.__name__}:\n"
for y in range(self.height):
for x in range(self.width):
match self.map[y, x]:
case 0:
s += "."
case 1:
s += "O"
case 2:
s += "#"
s += "\n"
s += ">"
return s
lines = [line.strip() for line in open('14.input').readlines()]
dish = Dish(lines)
dish.spin()
print(dish.load())