AoC 2024 day 16

 avatar
unknown
python
2 months ago
3.2 kB
150
Indexable
P=puzzle.splitlines()
M=defaultdict(); S=-1; E=-1; inf=999999                             # maze map, some infinite value
for j,r in enumerate(P):                                            # for each row
    for i,c in enumerate(r):                                        # for each maze cell
        p=i+1j*j; M[p]=[c,inf]                                      # memorize the contents with some infinite cost
        if c=='S': S=p                                              # memorize the Start position
        if c=='E': E=p                                              # memorize the End position

def travel():                                                       # travel from S to E at cheapest cost
    q=[]; v=defaultdict(lambda: inf); x=0                           # queue of paths, visited position/direction pairs, counter
    best=inf; bestpp=defaultdict(lambda: [])                        # best cost, best paths positions
    heapq.heappush(q,[0,x:=x+1,[S],1])                              # heapq for auto-sort, queue initial cost/path/direction
    while (q):                                                      # while we still have paths to explore
        c,_,pp,d=heapq.heappop(q); p=pp[-1]                         # pop the queued path/direction of lowest cost, last position of path
        if c<=best:                                                 # no need to test this path if its cost greater than best score
            if p==E: best=c; bestpp[c]+=pp                          # record a best score and its path positions, if we reach End position 
            v[(p,d)]=c                                              # record the cost at current position/direction visited pair (to later avoid greater ones)
            for nd in [1,1j,-1,-1j]:                                # for each neighbour directions
                np=p+nd                                             # position of the neighbour
                if M[np][0]!='#' and np not in pp:                  # if the neighbour cell is empty and not already in current path
                    nc=c+(1 if nd==d else 1001)                     # calculate the cost to go to move to this neighbour cell
                    if v[(np,nd)]>nc:                               # queue this neighbour new cost/path/direction unless it  was visited at lower cost
                        heapq.heappush(q,[nc,x:=x+1,pp+[np],nd])    # we use x unique counter before pp argument that contains non-hashable complex numbers  
    return(best,bestpp)                                             # return the best score and all positions of all paths with this score (could be multiple)

def part1():
    best,_=travel()                                                 # travel the maze for best score
    print(best)                                                     # display the best score

def part2():
    best,bestpp=travel()                                            # travel the maze for best score, best paths' positions
    print(len(set(bestpp[best])))                                   # display the number of unique positions of all paths with the best score
Leave a Comment