-
Notifications
You must be signed in to change notification settings - Fork 0
/
Solution_2021_15.swift
91 lines (74 loc) · 2.81 KB
/
Solution_2021_15.swift
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
//
// Solution_2021_15.swift
//
//
// Created by Ivan Chalov on 15.12.21.
//
import Foundation
import SortedCollections
struct Solution_2021_15: Solution {
var input: Input
func run() throws {
let input = try self.input.get()
.split(whereSeparator: \.isNewline)
.map { $0.map { Int(String($0))! }}
// ------- Part 1 -------
func solve(target: Point, map: [[Int]]) -> Int? {
let vertices = map.indices.flatMap { i in map[i].indices.map { j in Point(i: i, j: j) } }
var minDistance = Dictionary(uniqueKeysWithValues: vertices.map { ($0, Int.max) })
minDistance[vertices[0]] = 0
var queue = SortedSet([DistPoint(point: vertices[0], distance: 0)])
while !queue.isEmpty {
let min = queue.removeFirst()
if min.point == vertices.last {
return minDistance[min.point]!
}
for next in adjacent(i: min.point.i, j: min.point.j, map) {
let newDistance = min.distance + map[next.i][next.j]
if newDistance < minDistance[next]! {
queue.remove(DistPoint(point: next, distance: minDistance[next]!))
minDistance[next] = newDistance
queue.insert(DistPoint(point: next, distance: minDistance[next]!))
}
}
}
return nil
}
let part1 = solve(target: Point(i: 99, j: 99), map: input)!
print(part1)
// ------- Part 2 -------
var newMap = Array(repeating: Array(repeating: 0, count: 500), count: 500)
for d in 0..<5 {
for r in 0..<5 {
for i in input.indices {
for j in input[i].indices {
var newValue = input[i][j] + r + d
if newValue > 9 { newValue -= 9 }
newMap[d * input.count + i][r * input.first!.count + j] = newValue
}
}
}
}
let part2 = solve(target: Point(i: 499, j: 499), map: newMap)!
print(part2)
// ------- Test -------
assert(part1 == 361, "WA")
assert(part2 == 2838, "WA")
}
}
private struct Point: Hashable { var i, j: Int }
private struct DistPoint: Hashable, Comparable {
var point: Point, distance: Int
static func < (lhs: Self, rhs: Self) -> Bool {
lhs.distance < rhs.distance
}
}
private func adjacent(i: Int, j: Int, _ m: [[Int]]) -> [Point] {
[(1, 0), (0, 1), (0, -1), (-1, 0)]
.compactMap { dirI, dirJ in
let (idxI, idxJ) = (i + dirI, j + dirJ)
return m.indices ~= idxI && m[idxI].indices ~= idxJ
? Point(i: idxI, j: idxJ)
: nil
}
}