import Foundation struct Coord : Hashable, CustomStringConvertible { let (x, y): (Int, Int) var description: String { return "(\(x),\(y))" } } func readInput(_ fileName: String) throws -> [Coord] { let xy = try Regex(#"([0-9]+),([0-9]+)"#) return try String(contentsOfFile: fileName, encoding: .ascii) .split(separator: "\n") .compactMap { $0.wholeMatch(of: xy) } .map { Coord( x: Int($0.output[1].substring!)!, y: Int($0.output[2].substring!)! ) } } struct Map : CustomStringConvertible { let walls: Set let (w, h): (Int, Int) var description: String { let top = " \u{001B}[4m" + (0.. Int { return abs(a.x - b.x) + abs(a.y - b.y) } func bfs(from start: Coord, to end: Coord) -> Bool { var q: Set = [start] var seen: Set = [start] while !q.isEmpty { let cell = q.removeFirst() if cell == end { return true } [(0, -1), (0, 1), (-1, 0), (1, 0)].map { dy, dx in Coord(x: cell.x + dx, y: cell.y + dy)} .filter { c in c.x >= 0 && c.y >= 0 && c.x < w && c.y < h } .filter { !walls.contains($0) } .filter { !seen.contains($0) } .forEach { nb in seen.insert(nb) q.insert(nb) } } return false } } @main struct AoC { static func main() throws { let bytes = try readInput(CommandLine.arguments[1]) let w = Int(CommandLine.arguments[2]) ?? 71 let h = Int(CommandLine.arguments[3]) ?? 71 let startLimit = Int(CommandLine.arguments[4]) ?? 1024 var range = Array(startLimit.. 1 { let center = range.count/2 print("Trying \(range[center])...", terminator: "") let map = Map(walls: Set(bytes.prefix(range[center])), w: w, h: h) if map.bfs(from: Coord(x: 0, y: 0), to: Coord(x: w-1, y: h-1)) { print(" works") range = Array(range[center+1..