-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpartTwo.js
71 lines (62 loc) · 1.86 KB
/
partTwo.js
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
const partTwo = (input) => { // NOSONAR
input = input.split('\n').map((line) => [line[5], line[36]]);
const allSteps = [...new Set(input.flat())].sort();
function getRequirements(step) {
return input.filter(([, s]) => s === step).map(([s]) => s);
}
function canBeTaken(step, takenSteps) {
const reqs = getRequirements(step);
return reqs.every((req) => takenSteps.includes(req));
}
const NO_OF_WORKERS = 5;
let jobs = new Array(NO_OF_WORKERS).fill(null); // null represents an idle worker.
let takenSteps = '';
let availableSteps = allSteps.filter(
(step) => getRequirements(step).length === 0
);
let time = 0;
while (takenSteps.length < allSteps.length) {
// Take note of finished worker jobs:
const finished = new Set();
jobs = jobs.map((job) => {
if (job && job.end === time) {
finished.add(job.step);
return null;
}
return job;
});
takenSteps += [...finished].join('');
// Compute availableSteps:
const helperSet = new Set(availableSteps);
finished.forEach((step) => {
const next = input
.filter(([r, e]) => r === step && canBeTaken(e, takenSteps + step))
.map((s) => s[1]);
next.forEach((individualStep) => helperSet.add(individualStep));
});
availableSteps = [...helperSet].sort();
// Take jobs based on availableSteps:
jobs = jobs.map((job) => {
if (!job) {
const step = availableSteps.shift();
return step
? {
step,
end: time + step.charCodeAt(0) - 4
}
: null;
}
return job;
});
// Advance time to the end of the next job:
const newTime = jobs.reduce(
(min, job) => (job ? Math.min(min, job.end) : min),
Infinity
);
if (newTime < Infinity) {
time = newTime;
}
}
return time;
};
module.exports = partTwo;