summary refs log blame commit diff stats
path: root/day15.py
blob: 90aaed3f2a3317d96bedcc7c6e4597edad1203d4 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
#!/usr/bin/env python

import numpy as np
import math
from heapq import *
from collections import defaultdict

with open('day15.txt') as data:
    costs = []
    for line in data:
        costs.append(list(line.strip()))
    costs = np.array(costs).astype(int)

def a_star(costs) -> int:
    def h(point):
        m, n = point
        # approximate with straight line distance between points
        return math.sqrt((costs.shape[0]-m)**2 + (costs.shape[1]-n)**2)

    def neighbors(point):
        m, n = point
        neighboring = {(0, 1), (1, 0), (0, -1), (-1, 0)}
        return {(m+dx, n+dy) for dx, dy in neighboring
                if 0<=m+dx<costs.shape[0] and 0<=n+dy<costs.shape[1]}

    def path_sum(parents, current):
        complete = [current]
        while current in parents:
            current = parents[current]
            if current != (0, 0):
                complete.insert(0, current)
        return sum(map(lambda x: costs[x], complete))

    discovered = [(0,0)]
    parents = {}

    gScore = defaultdict(lambda : math.inf)
    gScore[(0,0)] = 0

    fScore = defaultdict(lambda : math.inf)
    fScore[(0,0)] = h((0,0))

    while discovered:
        if discovered[0] == (goal := (costs.shape[0]-1, costs.shape[1]-1)):
            return path_sum(parents, goal)

        current = heappop(discovered)
        for neighbor in neighbors(current):
            tentative = gScore[current] + costs[neighbor]
            if tentative < gScore[neighbor]:
                parents[neighbor] = current
                gScore[neighbor] = tentative
                fScore[neighbor] = tentative + h(neighbor)
                if neighbor not in discovered:
                    heappush(discovered, neighbor)
    else:
        return None
# part 1
print(a_star(costs))

# part 2
new_costs = np.zeros((costs.shape[0] * 5, costs.shape[1] * 5)).astype(int)

def increment(arr):
    arr += 1
    arr[arr > 9] = 1

xDim, yDim = costs.shape
for i in range(5):
    for j in range(5):
        copied = np.copy(costs)
        for _ in range(i+j):
            increment(copied)
        new_costs[xDim*i:xDim*(i+1), yDim*j:yDim*(j+1)] = copied

print(a_star(new_costs))