Last active
December 13, 2022 20:23
-
-
Save mkuliszkiewicz/399f56398e7c9da4ac3a724139fd6266 to your computer and use it in GitHub Desktop.
AoC Day 12 Task 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Path { | |
let point: Point | |
let previousPath: Path? | |
let length: Int | |
init(to point: Point, previousPath path: Path? = nil) { | |
self.point = point | |
self.length = 1 + (path?.length ?? 0) | |
self.previousPath = path | |
} | |
} | |
extension Path { | |
var array: [Point] { | |
var result: [Point] = [point] | |
var currentPath = self | |
while let path = currentPath.previousPath { | |
result.append(path.point) | |
currentPath = path | |
} | |
return result | |
} | |
} | |
let alphabet = Array("abcdefghijklmnopqrstuvwxyz") | |
func task1(input: String) -> Int { | |
let grid: [[Character]] = input | |
.components(separatedBy: CharacterSet.newlines) | |
.filter { !$0.isEmpty } | |
.map { Array($0) } | |
let maxX = grid[0].count | |
let maxY = grid.count | |
printGrid(grid: grid) | |
let startY = grid.firstIndex(where: { $0.contains("S") })! | |
let startX = grid[startY].firstIndex(where: { $0 == "S" })! | |
print(("start", startX, startY)) | |
let endY = grid.firstIndex(where: { $0.contains("E") })! | |
let endX = grid[endY].firstIndex(where: { $0 == "E" })! | |
print(("end", endX, endY)) | |
func val(_ point: Point) -> Character { | |
return grid[point.y][point.x] | |
} | |
func possiblePoints(for point: Point) -> [Point] { | |
var result: [Point] = [] | |
var directions: [(Int, Int)] = [(-1, 0), (0, 1), (1, 0), (0, -1)] | |
for (x, y) in directions { | |
guard | |
point.x + x < maxX, | |
point.x + x >= 0, | |
point.y + y < maxY, | |
point.y + y >= 0 | |
else { continue } | |
result.append(Point(x: point.x + x, y: point.y + y)) | |
} | |
let pointValue = val(point) | |
if pointValue == "S" { return result } | |
let currentValueIdx = alphabet.firstIndex(of: pointValue)! | |
let allowedIndices = Array(0...currentValueIdx + 1) | |
result = result.filter { | |
var targetPointVal = val($0) | |
if targetPointVal == "S" { return false } | |
if targetPointVal == "E" { | |
targetPointVal = "z" | |
} | |
let targetPointIdx = alphabet.firstIndex(of: targetPointVal)! | |
return allowedIndices.contains(targetPointIdx) | |
} | |
return result | |
} | |
func findPath(source: Point, destination: Point) -> Path? { | |
var paths: [Path] = [] { | |
didSet { | |
paths.sort { | |
return $0.length < $1.length | |
} | |
} | |
} | |
var visited: Set<Point> = [] | |
paths.append(Path(to: source)) | |
while !paths.isEmpty { | |
let currentPath = paths.removeFirst() | |
guard !visited.contains(currentPath.point) else { | |
continue | |
} | |
if currentPath.point == destination { | |
return currentPath | |
} | |
visited.insert(currentPath.point) | |
for nextPoint in possiblePoints(for: currentPath.point).filter({ !visited.contains($0) }) { | |
paths.append(Path.init(to: nextPoint, previousPath: currentPath)) | |
} | |
} | |
return nil | |
} | |
let startPoint = Point(x: startX, y: startY) | |
let endPoint = Point(x: endX, y: endY) | |
let shortestPath = findPath(source: startPoint, destination: endPoint)! | |
return shortestPath.length - 1 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func task12_2(input: String) -> Int { | |
var grid: [[Character]] = input | |
.components(separatedBy: CharacterSet.newlines) | |
.filter { !$0.isEmpty } | |
.map { Array($0) } | |
let maxX = grid[0].count | |
let maxY = grid.count | |
let endY = grid.firstIndex(where: { $0.contains("E") })! | |
let endX = grid[endY].firstIndex(where: { $0 == "E" })! | |
let endPoint = Point(x: endX, y: endY) | |
let numberGrid: [[UInt8]] = grid.map { row in | |
row.map { char in | |
if char == "S" { | |
return Character("a").asciiValue! | |
} | |
if char == "E" { | |
return Character("z").asciiValue! | |
} | |
return char.asciiValue! | |
} | |
} | |
func val(_ point: Point) -> UInt8 { | |
numberGrid[point.y][point.x] | |
} | |
func possiblePoints(for point: Point) -> [Point] { | |
var result: [Point] = [] | |
var directions: [(Int, Int)] = [(-1, 0), (0, 1), (1, 0), (0, -1)] | |
for (x, y) in directions { | |
guard | |
point.x + x < maxX, | |
point.x + x >= 0, | |
point.y + y < maxY, | |
point.y + y >= 0 | |
else { continue } | |
result.append(Point(x: point.x + x, y: point.y + y)) | |
} | |
let allowedValues = [val(point) - 1, val(point), val(point) + 1] | |
result = result.filter { proposedPoint in | |
print( | |
Int(val(proposedPoint)) - Int(val(point)) | |
) | |
return Int(val(proposedPoint)) - Int(val(point)) >= -1 | |
} | |
return result | |
} | |
var seenPoints = Set<Point>() | |
var paths: [Path] = [Path(to: endPoint)] | |
while !paths.isEmpty { | |
let currentPath = paths.removeFirst() | |
if val(currentPath.point) == Character("a").asciiValue! { | |
return currentPath.length - 1 | |
} | |
if seenPoints.contains(currentPath.point) { | |
continue | |
} | |
seenPoints.insert(currentPath.point) | |
let nextPoints = possiblePoints(for: currentPath.point).filter({ !seenPoints.contains($0) }) | |
for nextPoint in nextPoints { | |
paths.append(Path(to: nextPoint, previousPath: currentPath)) | |
} | |
} | |
return -1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment