-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday_20.py
148 lines (130 loc) · 3.91 KB
/
day_20.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import re
from datetime import datetime
from time import sleep
time_start = datetime.now()
with open('day_20.input', 'r') as file:
lines = file.readlines()
walls = {}
start = None
end = None
height = len(lines)
width = len(lines[0])
for y in range(height):
for x in range(width):
if lines[y][x] == "#":
# (Nanoseconds, cheated)
walls[x,y] = (0, False)
if lines[y][x] == "S":
start = x, y
if lines[y][x] == "E":
end = x, y
class RaceHorse:
def __init__(self, start, end):
self.pos = start
self.end = end
self.steps = 0
self.cheated = False
def get_moves(self):
x, y = self.pos
return [
(x-1, y),
(x+1, y),
(x, y+1),
(x, y-1)
]
def escape(self):
path = {self.pos: 0}
while self.pos != self.end:
moves = self.get_moves()
for move in moves:
if move in walls:
continue
if move in path:
continue
self.steps += 1
self.pos = move
path[move] = self.steps
# fancy_print(self)
# sleep(0.1)
return path
def cheat(self, path, cutoff):
total = 0
for x, y in path.keys():
steps = path[x,y]
if (x - 2, y) in path:
if path[x-2,y] - steps > cutoff:
total += 1
if (x + 2, y) in path:
if path[x+2,y] - steps > cutoff:
total += 1
if (x, y - 2) in path:
if path[x,y-2] - steps > cutoff:
total += 1
if (x, y + 2) in path:
if path[x,y+2] - steps > cutoff:
total += 1
return total
def cheat_time(self, time, path, cutoff):
total = 0
for x, y in path.keys():
steps = path[x,y]
if self.steps - steps < cutoff:
break
positions = {(x, y)}
for i in range(time):
new_positions = set()
for x_i, y_i in positions:
new_positions.add((x_i + 1, y_i))
new_positions.add((x_i - 1, y_i))
new_positions.add((x_i, y_i - 1))
new_positions.add((x_i, y_i + 1))
positions.update(new_positions)
for pos in positions:
if pos in path:
if path[pos] - steps - abs(x - pos[0]) - abs(y - pos[1]) >= cutoff:
total += 1
return total
# def fancy_print_debug_2(start, pos):
# for y in range(height):
# line = ""
# for x in range(width):
# if start == (x, y):
# line += "F"
# elif (x, y) in pos:
# line += "C"
#
# else:
# line += lines[y][x]
# print(line)
#
#
# def fancy_print_debug(start, end, path):
# for y in range(height):
# line = ""
# for x in range(width):
# if start == (x, y):
# line += '\033[92m'+ "F" + '\033[0m'
# elif end == (x, y):
# line += '\033[94m'+ "H" + '\033[0m'
# elif (x,y) in path:
# line += str(path[x,y])
# else:
# line += lines[y][x]
# print(line)
#
# def fancy_print(race: RaceHorse):
# for y in range(height):
# line = ""
# for x in range(width):
# if race.pos == (x, y):
# line += "S"
# else:
# line += lines[y][x]
# print(line)
race = RaceHorse(start, end)
# fancy_print(race)
path = race.escape()
print("part1", race.cheat(path, 100))
print("part2", race.cheat_time(20, path, 100))
print("Total time: ", datetime.now() - time_start)
#Total time: 0:00:13.792486