Skip to content

Instantly share code, notes, and snippets.

@alex-vasenin
Last active June 25, 2018 16:36
Show Gist options
  • Save alex-vasenin/cff6d7d9b36d2ad89507b56f055fa6ab to your computer and use it in GitHub Desktop.
Save alex-vasenin/cff6d7d9b36d2ad89507b56f055fa6ab to your computer and use it in GitHub Desktop.
A time saving affair in Swift (two cases timeouts)
import Foundation
func main() {
var input = [[Int]]()
for _ in 0..<3 { input.append(readInts()) }
for _ in 0..<input[2][0] { input.append(readInts()) }
let graph = RoadGraph(input: input)
//print(graph.description)
let result = graph.calcShortestPathLength()
print(result)
}
func readInts() -> [Int] { return readLine()!.split(separator: " ").map { Int($0)! } }
class RoadGraph: CustomStringConvertible {
private(set) var vertices: [Vertex]
let signalTime: Int
init(input: [[Int]]) {
let vertexCount = input[0][0]
self.signalTime = input[1][0]
self.vertices = stride(from: 0, to: vertexCount, by: 1).map { Vertex(id: $0) }
for nums in input.suffix(from: 3) {
let (from, to, length) = (nums[0]-1, nums[1]-1, nums[2])
vertices[from].edges.append(Edge(destination: to, length: length))
vertices[to].edges.append(Edge(destination: from, length: length))
}
}
var description: String {
let verticesDescriptions = vertices.map { $0.description } .joined(separator: "\n")
return "RoadGraph (\(signalTime) sec)\n\(verticesDescriptions)"
}
struct Vertex: CustomStringConvertible {
let id: Int
var edges: [Edge]
init(id: Int) { self.id = id; self.edges = [] }
var description: String { return "Vertex #\(id): \(edges)" }
}
struct Edge: CustomStringConvertible {
var destination, length: Int
var description: String { return "Edge \(destination)@\(length)" }
}
class Queue<Element>: CustomStringConvertible {
private var first: Wrapper<Element>? = nil
private var last: Wrapper<Element>? = nil
private(set) var count: Int = 0
init() { }
var hasElements: Bool { return first != nil }
func enqueue(_ element: Element) { let oldLast = last; last = Wrapper(element); if hasElements { oldLast?.next = last } else { first = last }; count += 1 }
func dequeu() -> Element? { let result = first?.content; first = first?.next; count -= 1; if !hasElements { last = nil }; return result }
var elements: [Element] { var result = [Element](); var current = first; while (current != nil) { result.append(current!.content); current = current!.next }; return result }
var description: String { return "Queue \(elements.description)" }
private class Wrapper<Element> {
var content: Element
var next: Wrapper?
init(_ content: Element, next: Wrapper? = nil) { self.content = content; self.next = next }
}
}
func calcShortestPathLength() -> Int {
var visitTime = Array(repeating: Int.max, count: vertices.count)
let queue = Queue<Vertex>()
queue.enqueue(vertices.first!)
visitTime[0] = 0
while queue.hasElements {
let vertex = queue.dequeu()!
let time = visitTime[vertex.id]
for edge in vertex.edges {
let dest = edge.destination
let newTime = dest != vertices.count-1 ? nextGreenTime(time + edge.length) : time + edge.length
guard newTime < visitTime[dest] else { continue }
visitTime[dest] = newTime
queue.enqueue(vertices[dest])
}
}
return visitTime.last!
}
func nextGreenTime(_ time: Int) -> Int {
let relative = time % (signalTime * 2)
let phase = relative / signalTime
if phase == 0 { // green light
return time
} else { // red light
let wait = (signalTime * 2) - relative
return time + wait
}
}
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment