1
1
from aoc import *
2
- from itertools import pairwise , combinations , repeat , product , accumulate , permutations , cycle , combinations_with_replacement
3
- from more_itertools import first_true , flatten , ncycles , first_true , zip_broadcast , windowed , chunked , take , peekable
4
- import re
5
- from blessed import BlessedList
6
- from collections import namedtuple , defaultdict , OrderedDict , Counter , deque , UserList
7
- import operator
8
- from operator import itemgetter
9
- from bisect import *
10
- from functools import reduce , cache , cmp_to_key
11
- import math
12
- from copy import deepcopy
13
- from math import ceil
2
+ from itertools import product
3
+ from collections import namedtuple , deque , UserList
14
4
from heapq import *
15
5
import sys
16
- from pprint import pprint as pp
17
- from statistics import mode
18
- from string import ascii_uppercase
19
6
import itertools
20
7
21
8
22
9
# Priority queue implementation from
23
10
# https://docs.python.org/3.3/library/heapq.html#priority-queue-implementation-notes
24
11
class PriorityQueue (UserList ):
25
12
def __init__ (self ):
26
- self .entry_finder = {} # mapping of tasks to entries
27
- self .REMOVED = '<removed-task>' # placeholder for a removed task
28
- self .counter = itertools .count () # unique sequence count
13
+ self .entry_finder = {} # mapping of tasks to entries
14
+ self .REMOVED = '<removed-task>' # placeholder for a removed task
15
+ self .counter = itertools .count () # unique sequence count
29
16
UserList .__init__ (self )
30
17
31
18
def add_task (self , task , priority = 0 ):
@@ -51,19 +38,19 @@ def pop_task(self):
51
38
return task
52
39
raise KeyError ('pop from an empty priority queue' )
53
40
41
+
54
42
# Dijkstra from https://rosettacode.org/wiki/Dijkstra%27s_algorithm#Python
55
43
inf = float ('inf' )
56
44
Edge = namedtuple ('Edge' , ['start' , 'end' , 'cost' ])
57
45
58
- class Graph ():
46
+
47
+ class Graph :
59
48
def __init__ (self , edges ):
60
49
self .edges = [Edge (* edge ) for edge in edges ]
61
50
# print(dir(self.edges[0]))
62
- self .vertices = {e .start for e in self .edges } | {e .end for e in self .edges }
63
-
64
- def add_edge (self , edge )
65
- self .edges .append (Edge (* edge ))
66
- self .vertices .extend ({edges [0 ], edges [1 ]})
51
+ self .vertices = {e .start for e in self .edges } | {
52
+ e .end for e in self .edges
53
+ }
67
54
68
55
def dijkstra (self , source , dest ):
69
56
assert source in self .vertices
@@ -85,7 +72,7 @@ def dijkstra(self, source, dest):
85
72
break
86
73
for v , cost in neighbours [u ]:
87
74
alt = dist [u ] + cost
88
- if alt < dist [v ]: # Relax (u,v,a)
75
+ if alt < dist [v ]: # Relax (u,v,a)
89
76
dist [v ] = alt
90
77
previous [v ] = u
91
78
q .add_task (v , alt )
@@ -99,11 +86,13 @@ def dijkstra(self, source, dest):
99
86
100
87
DIRS = ((- 1 , 0 ), (0 , 1 ), (1 , 0 ), (0 , - 1 ))
101
88
89
+
102
90
def main (infi : str ):
103
91
inp = lines_stripped (infi )
104
92
coords = set ()
105
- # for b in range(2966, len(inp)):
106
- for b in range (len (inp )):
93
+ # The start of the range was raised manually. TODO: binary search, or a
94
+ # better implementation of graph search.
95
+ for b in range (2900 , len (inp )):
107
96
for x in inp [:b ]:
108
97
nums = x .split (',' )
109
98
coords .add ((int (nums [0 ]), int (nums [1 ])))
@@ -113,13 +102,18 @@ def main(infi: str):
113
102
edges = []
114
103
for i , j in product (range (maxi ), range (maxj )):
115
104
for d in DIRS :
116
- if (i , j ) not in coords and 0 <= i + d [0 ] < maxi and 0 <= j + d [1 ] < maxj and (i + d [0 ], j + d [1 ]) not in coords :
105
+ if (
106
+ (i , j ) not in coords
107
+ and 0 <= i + d [0 ] < maxi
108
+ and 0 <= j + d [1 ] < maxj
109
+ and (i + d [0 ], j + d [1 ]) not in coords
110
+ ):
117
111
edges .append (((i , j ), (i + d [0 ], j + d [1 ]), 1 ))
118
112
edges .append (((i + d [0 ], j + d [1 ]), (i , j ), 1 ))
119
113
g = Graph (edges )
120
- path , shortest_length = g .dijkstra ((0 , 0 ), (maxi - 1 , maxj - 1 ))
114
+ path , shortest_length = g .dijkstra ((0 , 0 ), (maxi - 1 , maxj - 1 ))
121
115
if shortest_length == inf :
122
- return inp [b - 1 ]
116
+ return inp [b - 1 ]
123
117
# print(b, inp[b-1], shortest_length, path[-1])
124
118
125
119
@@ -131,5 +125,3 @@ def main(infi: str):
131
125
# test_and_submit(main, FILE_TEST, FILE_EXP, FILE, DAY)
132
126
# print(main(FILE_TEST))
133
127
print (main (FILE ))
134
-
135
- # 140 bad
0 commit comments