Skip to content

Commit

Permalink
day 20 part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
gereons committed Dec 20, 2024
1 parent ea5d2e9 commit 0ed3c48
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 4 deletions.
89 changes: 87 additions & 2 deletions Sources/Day20/Day20.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,103 @@
//

import AoCTools
import Collections

final class Day20: AOCDay {
let title = ""
let title = "Race Condition"

let grid: [[Character]]
let walls: Set<Point>
let start: Point
let end: Point

init(input: String) {
var points = input.lines.map { Array($0) }
var walls = Set<Point>()
var start: Point?
var end: Point?
for y in 0..<points.count {
for x in 0..<points[y].count {
let p = Point(x, y)
if points[p] == "S" {
start = p
} else if points[p] == "E" {
end = p
} else if points[p] == "#" {
walls.insert(p)
}
}
}
points[start!] = "."
points[end!] = "."
self.grid = points
self.walls = walls
self.start = start!
self.end = end!
}

func part1() -> Int {
0
part1(minTimeSaved: 100)
}

func part1(minTimeSaved: Int) -> Int {
let raceTrack = RaceTrack(grid: grid)
let regularTime = raceTrack.shortestTime(from: start, to: end)

var cheatCandidates = [Point]()
for wall in walls {
if grid[safe: wall + .left] == "." && grid[safe: wall + .right] == "." {
cheatCandidates.append(wall)
}
if grid[safe: wall + .up] == "." && grid[safe: wall + .down] == "." {
cheatCandidates.append(wall)
}
}

var timesSaved = [Int: Int]()
for cheat in cheatCandidates {
var grid = grid
grid[cheat] = "."
let cheatTrack = RaceTrack(grid: grid)
let cheatTime = cheatTrack.shortestTime(from: start, to: end)
timesSaved[regularTime - cheatTime, default: 0] += 1
}

return timesSaved.filter { $0.key >= minTimeSaved }.reduce(0) { $0 + $1.value }
}

func part2() -> Int {
0
}
}

struct RaceTrack {
let grid: [[Character]]

func shortestTime(from start: Point, to end: Point) -> Int {
var queue = Deque([(start, 0)])
var visited = Set([start])

while let (next, len) = queue.popFirst() {
if next == end {
return len
}
visited.insert(next)
for n in neighbors(of: next) {
if !visited.contains(n) {
queue.append((n, len + 1))
}
}
}
fatalError()
}

func neighbors(of point: Point) -> [Point] {
var n = [Point]()
for dir in Direction.orthogonal {
let p = point + dir
if grid[p] == "." { n.append(p) }
}
return n
}
}
19 changes: 17 additions & 2 deletions Tests/Day20Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,35 @@ import Testing
@testable import AdventOfCode

fileprivate let testInput = """
###############
#...#...#.....#
#.#.#.#.#.###.#
#S#...#.#.#...#
#######.#.#.###
#######.#.#...#
#######.#.###.#
###..E#...#...#
###.#######.###
#...###...#...#
#.#####.#.###.#
#.#...#.#.#...#
#.#.#.#.#.#.###
#...#...#...###
###############
"""

@Suite("Day 20 Tests")
struct Day20Tests {
@MainActor @Test("Day 20 Part 1")
func testDay20_part1() {
let day = Day20(input: testInput)
#expect(day.part1() == 0)
#expect(day.part1(minTimeSaved: 0) == 44)
}

@MainActor @Test("Day 20 Part 1 Solution")
func testDay20_part1_solution() {
let day = Day20(input: Day20.input)
#expect(day.part1() == 0)
#expect(day.part1() == 1327)
}

@MainActor @Test("Day 20 Part 2")
Expand Down

0 comments on commit 0ed3c48

Please sign in to comment.