-
Notifications
You must be signed in to change notification settings - Fork 1
/
day17.py
108 lines (100 loc) · 3.44 KB
/
day17.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
from collections import deque
import re
def parseInput(filepath, output):
f = open(filepath, "r")
data = f.read().splitlines()
xLineRegexp = r'x=(\d+), y=(\d+)\.\.(\d+)'
yLineRegexp = r'y=(\d+), x=(\d+)\.\.(\d+)'
xLinePattern = re.compile(xLineRegexp)
yLinePattern = re.compile(yLineRegexp)
for line in data:
m = xLinePattern.search(line)
if m is not None:
for y in range(int(m.group(2)), int(m.group(3))+1):
output.append((int(m.group(1)), y))
m = yLinePattern.search(line)
if m is not None:
for x in range(int(m.group(2)), int(m.group(3))+1):
output.append((x, int(m.group(1))))
def prepArea():
maxX = max(clayCoords, key=lambda c: c[0])[0] + 5
maxY = max(clayCoords, key=lambda c: c[1])[1] + 1
area = [['.' for x in range(maxX)] for y in range(maxY)]
area[0][500] = '+'
for clay in clayCoords:
area[clay[1]][clay[0]] = '#'
return area
def printArea(area):
for row in area:
print(''.join(row[400:900]))
def endOfAreaBelow(area, pos):
return pos[1] + 1 == len(area)
def runningWaterBelow(area, pos):
return area[pos[1]+1][pos[0]] == '|'
def runningWaterLeft(area, pos):
return area[pos[1]][pos[0]-1] == '|'
def runningWaterRight(area, pos):
return area[pos[1]][pos[0]+1] == '|'
def sandBelow(area, pos):
return area[pos[1]+1][pos[0]] == '.'
def sandLeft(area, pos):
return area[pos[1]][pos[0]-1] == '.'
def sandRight(area, pos):
return area[pos[1]][pos[0]+1] == '.'
def clayLeft(area, pos):
return area[pos[1]][pos[0]-1] == '#'
def clayRight(area, pos):
return area[pos[1]][pos[0]+1] == '#'
def runWater(area):
startingPos = (500, 0)
currentPos = startingPos
currentRow = deque([currentPos])
stack = deque()
while True:
if endOfAreaBelow(area, currentPos):
currentRow = stack.pop()
currentPos = currentRow[0]
elif runningWaterBelow(area, currentPos):
if runningWaterLeft(area, currentPos):
currentRow = stack.pop()
currentPos = currentRow[0]
elif runningWaterRight(area, currentPos):
currentPos = currentRow[-1]
else:
currentRow = stack.pop()
currentPos = currentRow[0]
elif sandBelow(area, currentPos):
area[currentPos[1]+1][currentPos[0]] = '|'
currentPos = (currentPos[0], currentPos[1]+1)
stack.append(currentRow)
currentRow = deque([currentPos])
elif sandLeft(area, currentPos):
area[currentPos[1]][currentPos[0]-1] = '|'
currentPos = (currentPos[0]-1, currentPos[1])
currentRow.appendleft(currentPos)
elif sandRight(area, currentPos):
area[currentPos[1]][currentPos[0]+1] = '|'
currentPos = (currentPos[0]+1, currentPos[1])
currentRow.append(currentPos)
elif clayRight(area, currentPos):
leftMost = currentRow[0]
if sandLeft(area, leftMost):
currentRow = stack.pop()
currentPos = currentRow[0]
continue
while currentRow:
pos = currentRow.pop()
area[pos[1]][pos[0]] = '~'
currentRow = stack.pop()
currentPos = currentRow[0]
elif clayLeft(area, currentPos):
currentPos = currentRow[-1]
if currentPos == startingPos:
return # back to start again
clayCoords = []
parseInput("day17/input", clayCoords)
area = prepArea()
runWater(area)
minY = min(clayCoords, key=lambda c: c[1])[1]
print("Total water:", sum(sum(1 for pos in row if pos == "~" or pos == "|") for row in area[minY:]))
print("Still water:", sum(sum(1 for pos in row if pos == "~") for row in area))