bfs and binary search
This commit is contained in:
@@ -33,27 +33,25 @@ struct Map : CustomStringConvertible {
|
|||||||
func heur(_ a: Coord, _ b: Coord) -> Int {
|
func heur(_ a: Coord, _ b: Coord) -> Int {
|
||||||
return abs(a.x - b.x) + abs(a.y - b.y)
|
return abs(a.x - b.x) + abs(a.y - b.y)
|
||||||
}
|
}
|
||||||
func astar(from start: Coord, to end: Coord) -> Int? {
|
func bfs(from start: Coord, to end: Coord) -> Bool {
|
||||||
var q = Heap<(Coord, Int)>(comparator: { l, r in l.1 < r.1 })
|
var q: Set<Coord> = [start]
|
||||||
var seen: [Coord: Int] = [start: 0]
|
var seen: Set<Coord> = [start]
|
||||||
q.insert((start, heur(start, end)))
|
while !q.isEmpty {
|
||||||
while let (cell, _) = q.pop() {
|
let cell = q.removeFirst()
|
||||||
if cell == end {
|
if cell == end {
|
||||||
return seen[cell]
|
return true
|
||||||
}
|
}
|
||||||
[(0, -1), (0, 1), (-1, 0), (1, 0)].map { dy, dx in
|
[(0, -1), (0, 1), (-1, 0), (1, 0)].map { dy, dx in
|
||||||
Coord(x: cell.x + dx, y: cell.y + dy)}
|
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 { c in c.x >= 0 && c.y >= 0 && c.x < w && c.y < h }
|
||||||
.filter { !walls.contains($0) }
|
.filter { !walls.contains($0) }
|
||||||
|
.filter { !seen.contains($0) }
|
||||||
.forEach { nb in
|
.forEach { nb in
|
||||||
let newCost = seen[cell]! + 1
|
seen.insert(nb)
|
||||||
if seen[nb, default: w*h] > newCost {
|
q.insert(nb)
|
||||||
seen[nb] = newCost
|
|
||||||
q.insert((nb, newCost + heur(nb, end)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return false
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,19 +62,26 @@ struct AoC {
|
|||||||
let w = Int(CommandLine.arguments[2]) ?? 71
|
let w = Int(CommandLine.arguments[2]) ?? 71
|
||||||
let h = Int(CommandLine.arguments[3]) ?? 71
|
let h = Int(CommandLine.arguments[3]) ?? 71
|
||||||
let startLimit = Int(CommandLine.arguments[4]) ?? 1024
|
let startLimit = Int(CommandLine.arguments[4]) ?? 1024
|
||||||
for limit in startLimit..<bytes.count {
|
var range = Array(startLimit..<bytes.count)
|
||||||
let map = Map(walls: Set(bytes.prefix(limit)), w: w, h: h)
|
while range.count > 1 {
|
||||||
if let cost = map.astar(
|
let center = range.count/2
|
||||||
from: Coord(x: 0, y: 0),
|
print("Trying \(range[center])...", terminator: "")
|
||||||
to: Coord(x: map.w - 1, y: map.h - 1)
|
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("\(limit): \(cost)")
|
print(" works")
|
||||||
|
range = Array(range[center+1..<range.count])
|
||||||
} else {
|
} else {
|
||||||
print(map)
|
print(" blocked")
|
||||||
print("found byte \(limit-1): \(bytes[limit-1])")
|
range = Array(range[0..<center])
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let map = Map(walls: Set(bytes.prefix(range[0])), w: w, h: h)
|
||||||
|
print(map)
|
||||||
|
if map.bfs(from: Coord(x: 0, y: 0), to: Coord(x: w-1, y: h-1)) {
|
||||||
|
print("at \(range[0]): \(bytes[range[0]])")
|
||||||
|
} else {
|
||||||
|
print("at \(range[0] + 1): \(bytes[range[0] + 1])")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user