46 lines
1.3 KiB
Swift
46 lines
1.3 KiB
Swift
import Foundation
|
|
|
|
typealias Network = [String: Set<String>]
|
|
|
|
func readInput(_ filePath: String) throws -> Network {
|
|
var map: Network = [:]
|
|
try String(contentsOfFile: filePath, encoding: .ascii)
|
|
.split(separator: "\n").map { $0.split(separator: "-") }
|
|
.map { (String($0[0]), String($0[1])) }.forEach { m1, m2 in
|
|
map[m1, default: []].insert(m2)
|
|
map[m2, default: []].insert(m1)
|
|
}
|
|
return map
|
|
}
|
|
|
|
func bronkerbosch(
|
|
_ network: Network, r: Set<String>, p: Set<String>, x: Set<String>
|
|
) -> Set<String>? {
|
|
if p.count == 0 {
|
|
return x.count == 0 ? r : nil
|
|
}
|
|
var maxClique: Set<String>? = nil
|
|
var nextP = p
|
|
var nextX = x
|
|
let u = p.union(x).first! // can also choose highest degree node
|
|
for v in p.subtracting(network[u]!) {
|
|
if let clique = bronkerbosch(network,
|
|
r: r.union([v]),
|
|
p: nextP.intersection(network[v]!),
|
|
x: nextX.intersection(network[v]!)
|
|
) {
|
|
if clique.count > (maxClique ?? []).count {
|
|
maxClique = clique
|
|
}
|
|
}
|
|
nextP.remove(v)
|
|
nextX.insert(v)
|
|
}
|
|
return maxClique
|
|
}
|
|
|
|
let conns = try readInput(CommandLine.arguments[1])
|
|
let clique = bronkerbosch(conns, r: [], p: Set(conns.keys), x: [])
|
|
print(Array(clique ?? []).sorted().joined(separator: ","))
|
|
|