vChewing-macOS/Packages/vChewing_Megrez/Sources/Megrez/2_Walker.swift

92 lines
3.1 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Swiftified and further development by (c) 2022 and onwards The vChewing Project (MIT License).
// Was initially rebranded from (c) Lukhnos Liu's C++ library "Gramambular 2" (MIT License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
public extension Megrez.Compositor {
/// walkedNodes
///
///
/// 使 Cormen 2001
///
///
/// `G = (V, E)` `O(|V|+|E|)` `G`
/// 使
/// - Returns:
@discardableResult mutating func walk() -> (walkedNode: [Node], succeeded: Bool) {
var result = [Node]()
defer { walkedNodes = result }
guard !spans.isEmpty else { return (result, true) }
var vertexSpans = [[Vertex]]()
for _ in spans {
vertexSpans.append(.init())
}
for (i, span) in spans.enumerated() {
for j in 1 ... span.maxLength {
if let theNode = span.nodeOf(length: j) {
vertexSpans[i].append(.init(node: theNode))
}
}
}
let terminal = Vertex(node: .init(keyArray: ["_TERMINAL_"]))
var root = Vertex(node: .init(keyArray: ["_ROOT_"]))
for (i, vertexSpan) in vertexSpans.enumerated() {
for vertex in vertexSpan {
let nextVertexPosition = i + vertex.node.spanLength
if nextVertexPosition == vertexSpans.count {
vertex.edges.append(terminal)
continue
}
for nextVertex in vertexSpans[nextVertexPosition] {
vertex.edges.append(nextVertex)
}
}
}
root.distance = 0
root.edges.append(contentsOf: vertexSpans[0])
var ordered = topologicalSort(root: &root)
for (j, neta) in ordered.reversed().enumerated() {
for (k, _) in neta.edges.enumerated() {
relax(u: neta, v: &neta.edges[k])
}
ordered[j] = neta
}
var iterated = terminal
var walked = [Node]()
var totalLengthOfKeys = 0
while let itPrev = iterated.prev {
walked.append(itPrev.node)
iterated = itPrev
totalLengthOfKeys += iterated.node.spanLength
}
//
ordered.removeAll()
vertexSpans.removeAll()
iterated.destroy()
root.destroy()
terminal.destroy()
guard totalLengthOfKeys == keys.count else {
print("!!! ERROR A")
return (result, false)
}
guard walked.count >= 2 else {
print("!!! ERROR B")
return (result, false)
}
walked = walked.reversed()
walked.removeFirst()
result = walked
return (result, true)
}
}