-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday07.go
More file actions
268 lines (225 loc) · 7.74 KB
/
day07.go
File metadata and controls
268 lines (225 loc) · 7.74 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
package main
import (
"fmt"
"sort"
"os"
"bufio"
"flag"
"strings"
)
// Each worker has a workItem and a time it will take to complete that workitem
type workerStruct struct {
timeToComplete int
workItem string
}
// Take the first item out of the list of strings passed in (toDo)
// Returns 3:
// - string: the item removed from the List
// - []string: the list of strings with the item removed
// - bool: true/false on whether an item was available for removal or not
func popTopItem(toDo []string)(string, []string, bool) {
var popItem string
if len(toDo) == 0 {
return "", toDo, false
}
popItem = toDo[0]
toDo = removeItem(toDo, toDo[0])
return popItem, toDo, true
}
func addItemSorted(toDo []string, itemAdd string) ([]string) {
var foundIt bool = false
for i := 0; i < len(toDo) && !foundIt; i++ {
if toDo[i] == itemAdd {
foundIt = true
}
}
if !foundIt {
toDo = append(toDo, itemAdd)
sort.Strings(toDo)
}
return toDo
}
func removeItem(toDo []string, itemRemove string) ([]string) {
var toDoReplace [] string
for i := 0; i < len(toDo); i++ {
if toDo[i] != itemRemove {
toDoReplace = addItemSorted(toDoReplace, toDo[i])
}
}
return toDoReplace
}
// Read the text file passed in by name into a array of strings
// Returns the array as the first return variable
func readLines(filename string) ([]string, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines, scanner.Err()
}
func printStringArray(tempString []string) {
// Loop through the array and print each line
for i:= 0; i < len(tempString); i++ {
fmt.Println(tempString[i])
}
}
// Loop through toDoList looking for workitem
// Remove workitem from all toDoList preRegs
// Any outcomeSteps with no preReqSteps left are put onto the reducedNoPreReqList
func workItemCompleted(workItem string, toDoList map[string]string, reducedNoPreReqList []string) (map[string]string, []string) {
for k, _ := range toDoList {
toDoList[k] = strings.Replace(toDoList[k], workItem, "", -1)
if toDoList[k] == "" {
// We've removed the last preReq so can add this to the reducedNoPreReqList
delete(toDoList, k)
reducedNoPreReqList = addItemSorted(reducedNoPreReqList, k)
}
}
return toDoList, reducedNoPreReqList
}
// Checks if an item already exists in the toDoList. If not, it adds it in there.
func checkWorkList(noPreReqList []string, toDoList map[string]string) []string {
var reducedNoPreReqList []string
for i := 0; i < len(noPreReqList); i++ {
if _, ok := toDoList[noPreReqList[i]]; !ok {
reducedNoPreReqList = addItemSorted(reducedNoPreReqList, noPreReqList[i])
}
}
return reducedNoPreReqList
}
// Carries out the work for PartA
func goPartA(reducedNoPreReqList []string, toDoList map[string]string) string {
var solutionOrder string
var workToDo bool = true
var workItem string
var ok bool
for workToDo {
workItem, reducedNoPreReqList, ok = popTopItem(reducedNoPreReqList)
if !ok {
workToDo = false
continue
} else {
solutionOrder += workItem
// Remove completed item from toDoList
toDoList, reducedNoPreReqList = workItemCompleted(workItem, toDoList, reducedNoPreReqList)
}
}
return solutionOrder
}
// Carries out the work for PartA
func goPartB(reducedNoPreReqList []string, toDoList map[string]string, timeConst int, numWorkers int) (string, int) {
var solutionOrder string
var workToDo bool = true
var workInProgress int = 0
var tempWorkItem string
var ok bool
var currentTime int = 0
workers := make([]workerStruct, numWorkers)
for i := 0; i < len(workers); i++ {
fmt.Println("workers", i, workers[i])
if workers[i].workItem == "" {
fmt.Println("Worker Ready to go:", i)
}
}
fmt.Println("Time Const is:", timeConst)
fmt.Println("Second Worker 1 Worker 2 Done")
for workToDo || workInProgress > 0 {
// Check if any work has completed
// If it has, then add the completed item to solutionOrder and return the Worker to being ready
// Any worker found that isn't busy, grab an item from the worklist reducedNoPreReqList (if any)
// and give to that worker
for i := 0; i < len(workers); i++ {
if workers[i].timeToComplete == currentTime && currentTime > 0 {
// We have a finisher!
solutionOrder += workers[i].workItem
// Remove completed item from toDoList
toDoList, reducedNoPreReqList = workItemCompleted(workers[i].workItem, toDoList, reducedNoPreReqList)
// Clear the workItem from the worker
workers[i].workItem = "-"
workInProgress--
// Avoid time counting upwards
}
// no else. we want a free worker to be picked up immediately
if workers[i].workItem == "" || workers[i].workItem == "-" {
// Worker ready and waiting for orders
tempWorkItem, reducedNoPreReqList, ok = popTopItem(reducedNoPreReqList)
if !ok {
workToDo = false
// continue
} else {
workers[i].workItem = tempWorkItem
// Time is currentTime + timeConst + number relating to letter (1-26)
workers[i].timeToComplete = currentTime + int(tempWorkItem[0]) + timeConst - 64
//fmt.Println("Time to complete for:", tempWorkItem, workers[i].timeToComplete)
workInProgress++
}
}
}
if len(workers) > 4 {
fmt.Printf("%d, %s, %s, %s, %s, %s, %s, %d\n", currentTime, workers[0].workItem, workers[1].workItem, workers[2].workItem, workers[3].workItem, workers[4].workItem, solutionOrder, workInProgress)
} else {
if len(workers) == 2 {
fmt.Printf("%d, %s, %s, %s, %d\n", currentTime, workers[0].workItem, workers[1].workItem, solutionOrder, workInProgress)
} else {
fmt.Printf("%d, %s, %s, %d\n", currentTime, workers[0].workItem, solutionOrder, workInProgress)
}
}
currentTime++
}
return solutionOrder, currentTime - 2
}
func stepOrder(fileName string, part string, timeconst int, numWorkers int) (string, int) {
var noPreReqList []string
var reducedNoPreReqList []string
var toDoList = make(map[string]string)
var solutionOrder string
var currentTime int = 0
// Read contents of file into a string array then sort that array
fileContents, _ := readLines(fileName)
for i := 0; i < len(fileContents); i++ {
var preReqStep string
var outcomeStep string
fmt.Sscanf(fileContents[i], "Step %s must be finished before step %s can begin.", &preReqStep, &outcomeStep)
toDoList[outcomeStep] += preReqStep
if toDoList[preReqStep] == "" {
noPreReqList = addItemSorted(noPreReqList, preReqStep)
}
}
// Double check the Start List (reducedNoPreReqList) is correct
reducedNoPreReqList = checkWorkList(noPreReqList, toDoList)
if part == "a" {
solutionOrder = goPartA(reducedNoPreReqList, toDoList)
} else {
solutionOrder, currentTime = goPartB(reducedNoPreReqList, toDoList, timeconst, numWorkers)
}
return solutionOrder, currentTime
}
// Main routine
func main() {
var solutionOrder string
var currentTime int
fileNamePtr := flag.String("file", "input1.txt", "A filename containing input strings")
execPartPtr := flag.String("part", "a", "Which part of day07 do you want to calc (a or b)")
timeConstantPtr := flag.Int("const", 0, "Time constant to add to each task for part b")
numWorkersPtr := flag.Int("workers", 1, "Number of workers to use in part b")
flag.Parse()
switch *execPartPtr {
case "a":
solutionOrder, currentTime = stepOrder(*fileNamePtr, "a", 0, 1)
fmt.Println("Part a - Order of steps:", solutionOrder)
case "b":
if *numWorkersPtr < 1 {
*numWorkersPtr = 1
}
solutionOrder, currentTime = stepOrder(*fileNamePtr, "b", *timeConstantPtr, *numWorkersPtr)
fmt.Printf("Part b - Order of steps: %s Time: %d\n", solutionOrder, currentTime)
default:
fmt.Println("Bad part choice. Available choices are 'a' and 'b'")
}
}