-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.swift
104 lines (77 loc) · 2.84 KB
/
main.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import Foundation
private typealias Graph = [String: Set<String>]
private typealias WeightedGraph = [String: [String: Int]]
func main() throws {
let isTestMode = CommandLine.arguments.contains("test")
let input: [String] = try readInput(fromTestFile: isTestMode)
let invertedGraph = buildInvertedGraph(input)
var visited: Set<String> = []
print(traverse(invertedGraph, "shiny gold", &visited) - 1)
let weightedGraph = buildGraph(input)
print(partTwoTraverse(weightedGraph, "shiny gold") - 1)
}
private func partTwoTraverse(_ graph: WeightedGraph, _ node: String) -> Int {
var total = 1
let children = graph[node]!
for (colour, value) in children {
total += value * partTwoTraverse(graph, colour)
}
return total
}
private func traverse(_ graph: Graph, _ node: String, _ visited: inout Set<String>) -> Int {
if visited.contains(node) { return 0 }
visited.insert(node)
var numberOfBagColours = 1
for neighbour in graph[node]! {
numberOfBagColours += traverse(graph, neighbour, &visited)
}
return numberOfBagColours
}
private func buildGraph(_ input: [String]) -> WeightedGraph {
var graph: WeightedGraph = [:]
let regex = Regex("^(\\w+ \\w+) bags contain (.+)\\.$")
for inputLine in input {
let matches = regex.getMatches(in: inputLine)
let destination = matches[0]
let sources: [String: Int]
if matches[1] == "no other bags" {
sources = [:]
} else {
let separatedSources = matches[1].components(separatedBy: ", ")
var tempSources: [String: Int] = [:]
for source in separatedSources {
let regex = Regex("(\\d+) (\\w+ \\w+) bags?")
let matches = regex.getMatches(in: source)
tempSources[matches[1]] = Int(matches[0])!
}
sources = tempSources
}
graph[destination] = sources
}
return graph
}
private func buildInvertedGraph(_ input: [String]) -> Graph {
var graph: Graph = [:]
let regex = Regex("^(\\w+ \\w+) bags contain (.+)\\.$")
for inputLine in input {
let matches = regex.getMatches(in: inputLine)
let destination = matches[0]
if graph[destination] == nil {
graph[destination] = []
}
if matches[1] != "no other bags" {
let sources = matches[1].components(separatedBy: ", ")
for source in sources {
let regex = Regex("(\\d+) (\\w+ \\w+) bags?")
let matches = regex.getMatches(in: source)
if graph[matches[1]] == nil {
graph[matches[1]] = [destination]
} else {
graph[matches[1]] = graph[matches[1]]!.union([destination])
}
}
}
}
return graph
}
Timer.time(main)