Last active
June 25, 2018 16:36
-
-
Save alex-vasenin/cff6d7d9b36d2ad89507b56f055fa6ab to your computer and use it in GitHub Desktop.
A time saving affair in Swift (two cases timeouts)
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
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