-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday7.nim
124 lines (101 loc) · 3.46 KB
/
day7.nim
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import sets
import strscans
import strutils
import tables
# Input file path
let inputFile = "input.txt"
# Declare bag type as string
type
Bag = string
# Parse line to get bag containers
proc parseLineContainer(containerTable: var Table[Bag, HashSet[Bag]],
line: string) =
# Divide into container and content
let subStrings = line.split(" contain ")
let containerString = subStrings[0]
let contentString = subStrings[1]
# Extract container
let container = containerString[0 .. ^6]
# Parse content
var contentList: HashSet[Bag]
if containerString != "no other bags":
let splitContentString = contentString[0 .. ^2].split(", ")
for contentSection in splitContentString:
var
count: int
bag: string
description, color: string
discard scanf(contentSection, "$i $* $* ", count, description, color)
bag = description & " " & color
contentList.incl(bag)
# Store in container table
for content in contentList:
if content notin containerTable:
var hashSet: HashSet[Bag]
containerTable[content] = hashSet
containerTable[content].incl(container)
# Find containers for a bag recursively
proc findContainers(containedTable: Table[Bag, HashSet[Bag]],
currentNode: Bag, canBeHoldIn: var HashSet[Bag]) =
if currentNode in containedTable:
for node in containedTable[currentNode]:
if node notin canBeHoldIn:
canBeHoldIn.incl(node)
findContainers(containedTable, node, canBeHoldIn)
# Parse input to get containers
var containedIn: Table[Bag, HashSet[Bag]]
for line in lines inputFile:
containedIn.parseLineContainer(line)
# Find containers for the bag
var canBeHoldIn: HashSet[Bag]
let myBag: Bag = "shiny gold"
findContainers(containedIn, myBag, canBeHoldIn)
# Print results
echo "--- Part 1 Report ---"
echo "Containers found = " & $canBeHoldIn.len
## Part 2
# Bag content type
type
BagContent = tuple
bag: Bag
count: int
# Parse line to get bag containers
proc parseLineContent(contentTable: var Table[Bag, HashSet[BagContent]],
line: string) =
let subStrings = line.split(" contain ")
let containerString = subStrings[0]
let contentString = subStrings[1]
let container = containerString[0 .. ^6]
var contentList: HashSet[Bag]
if containerString != "no other bags":
let splitContentString = contentString[0 .. ^2].split(", ")
for contentSection in splitContentString:
var
count: int
bag: string
description, color: string
discard scanf(contentSection, "$i $* $* ", count, description, color)
bag = description & " " & color
contentList.incl(bag)
if container notin contentTable:
var hashSet: HashSet[BagContent]
contentTable[container] = hashSet
contentTable[container].incl((bag, count))
# Find number of bags to be hold
proc countContainedBags(contentTable: Table[Bag, HashSet[BagContent]],
currentBag: Bag): int =
if currentBag in contentTable:
for content in contentTable[currentBag]:
# Bags contained plus the bag itself multiplied by the number of bags
# of that type
result += content.count * (1 + countContainedBags(contentTable,
content.bag))
# Parse input to get contents
var mustHold: Table[Bag, HashSet[BagContent]]
for line in lines inputFile:
mustHold.parseLineContent(line)
# Count contained bags
let containedBagCount = countContainedBags(mustHold, myBag)
# Print results
echo "--- Part 2 Report ---"
echo "Contents found = " & $containedBagCount