-
Notifications
You must be signed in to change notification settings - Fork 0
/
day7-2.p
165 lines (131 loc) · 5.89 KB
/
day7-2.p
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
/*
--- Day 7: The Sum of Its Parts ---
--- Part Two ---
As you're about to begin construction, four of the Elves offer to help. "The sun will set soon; it'll go faster if we work together." Now, you need to account for multiple people working on steps simultaneously. If multiple steps are available, workers should still begin them in alphabetical order.
Each step takes 60 seconds plus an amount corresponding to its letter: A=1, B=2, C=3, and so on. So, step A takes 60+1=61 seconds, while step Z takes 60+26=86 seconds. No time is required between steps.
To simplify things for the example, however, suppose you only have help from one Elf (a total of two workers) and that each step takes 60 fewer seconds (so that step A takes 1 second and step Z takes 26 seconds). Then, using the same instructions as above, this is how each second would be spent:
Second Worker 1 Worker 2 Done
0 C .
1 C .
2 C .
3 A F C
4 B F CA
5 B F CA
6 D F CAB
7 D F CAB
8 D F CAB
9 D . CABF
10 E . CABFD
11 E . CABFD
12 E . CABFD
13 E . CABFD
14 E . CABFD
15 . . CABFDE
Each row represents one second of time. The Second column identifies how many seconds have passed as of the beginning of that second. Each worker column shows the step that worker is currently doing (or . if they are idle). The Done column shows completed steps.
Note that the order of the steps has changed; this is because steps now take time to finish and multiple workers can begin multiple steps simultaneously.
In this example, it would take 15 seconds for two workers to complete these steps.
With 5 workers and the 60+ second step durations described above, how long will it take to complete all of the steps?
*/
&GLOBAL-DEFINE xiNumWorkers 5
DEFINE VARIABLE cLine AS CHARACTER EXTENT 10 NO-UNDO.
DEFINE VARIABLE cStep AS CHARACTER NO-UNDO.
DEFINE VARIABLE cSteps AS CHARACTER NO-UNDO.
DEFINE VARIABLE iSteps AS INTEGER NO-UNDO.
DEFINE VARIABLE iTime AS INTEGER NO-UNDO.
DEFINE VARIABLE iWorker AS INTEGER NO-UNDO.
DEFINE VARIABLE lStep AS LOGICAL NO-UNDO.
DEFINE TEMP-TABLE ttStep NO-UNDO
FIELD id AS CHARACTER
FIELD lDone AS LOGICAL
INDEX ix IS PRIMARY UNIQUE id.
DEFINE TEMP-TABLE ttOrder NO-UNDO
FIELD cStepFrom AS CHARACTER
FIELD cStepTo AS CHARACTER
FIELD lReady AS LOGICAL
INDEX ix IS PRIMARY UNIQUE cStepFrom cStepTo.
DEFINE TEMP-TABLE ttWorker NO-UNDO
FIELD iBusyTime AS INTEGER
FIELD cOngoingStep AS CHARACTER
INDEX ix iBusyTime.
DEFINE BUFFER bttOrder FOR ttOrder.
ETIME(YES).
INPUT FROM C:\User\JCCARDOT\Perso\Travail\aoc\aoc2018\day7.txt.
REPEAT:
IMPORT DELIMITER " " cLine.
/* cLine[2] before cLine[8] */
FIND ttStep WHERE ttStep.id = cLine[2] NO-ERROR.
IF NOT AVAILABLE ttStep THEN DO:
CREATE ttStep.
ASSIGN ttStep.id = cLine[2].
END.
FIND ttStep WHERE ttStep.id = cLine[8] NO-ERROR.
IF NOT AVAILABLE ttStep THEN DO:
CREATE ttStep.
ASSIGN ttStep.id = cLine[8].
END.
FIND ttOrder WHERE ttOrder.cStepFrom = cLine[2] AND ttOrder.cStepTo = cLine[8] NO-ERROR.
IF NOT AVAILABLE ttOrder THEN DO:
CREATE ttOrder.
ASSIGN ttOrder.cStepFrom = cLine[2]
ttOrder.cStepTo = cLine[8].
END.
END.
INPUT CLOSE.
FOR EACH ttStep:
iSteps = iSteps + 1.
END.
/* find start(s) and create corresponding ttOrders */
FOR EACH ttStep WHERE BY ttStep.id:
IF NOT CAN-FIND(FIRST ttOrder WHERE ttOrder.cStepTo = ttStep.id) THEN DO:
CREATE ttOrder.
ASSIGN ttOrder.cStepTo = ttStep.id
ttOrder.lReady = YES.
END.
END.
/* create the workers */
DO iWorker = 1 TO {&xiNumWorkers}:
CREATE ttWorker.
ASSIGN ttWorker.iBusyTime = 0.
END.
/* then process ready links */
blk:
DO WHILE iSteps > 0 OR CAN-FIND(FIRST ttWorker WHERE ttWorker.iBusyTime > 0):
FOR EACH ttWorker WHERE ttWorker.iBusyTime = 0: /* for each available worker... */
/* get next available step */
IF iSteps > 0 THEN DO:
FOR EACH ttOrder WHERE ttOrder.lReady = YES
,FIRST ttStep WHERE ttStep.id = ttOrder.cStepTo AND ttStep.lDone = NO
BY ttOrder.cStepTo:
IF CAN-FIND(FIRST bttOrder WHERE bttOrder.cStepTo = ttOrder.cStepTo AND bttOrder.lReady = NO) THEN
NEXT.
ttStep.lDone = ? /* means ongoing */.
LEAVE.
END.
IF AVAILABLE ttStep THEN ASSIGN
ttWorker.cOngoingStep = ttStep.id
ttWorker.iBusyTime = 60 + ASC(ttStep.id) - 64.
END.
END. /* for each available worker... */
iTime = iTime + 1.
FOR EACH ttWorker WHERE ttWorker.iBusyTime > 0:
ttWorker.iBusyTime = ttWorker.iBusyTime - 1.
IF ttWorker.iBusyTime = 0 THEN DO:
cSteps = cSteps + ttWorker.cOngoingStep.
FIND ttStep WHERE ttStep.id = ttWorker.cOngoingStep.
FOR EACH bttOrder WHERE bttOrder.cStepFrom = ttWorker.cOngoingStep:
bttOrder.lReady = YES.
END.
ASSIGN
iSteps = iSteps - 1
ttStep.lDone = YES
ttWorker.cOngoingStep = "".
END.
END.
END.
MESSAGE ETIME SKIP
cSteps SKIP
iTime
VIEW-AS ALERT-BOX INFO BUTTONS OK.
/* 5752 */
/* LRVAGPZHFOTCKWENBXIMSUDJQY */
/* 936 */