type Rules = {
[number: number]: Array<number>,
};
type InputData = {
rules: Rules,
updates: Array<Array<number>>,
};
type ValidityStatus = {
item: Array<number>,
isValid: boolean,
};
const solution: Fn = async ({ rules, updates }) => {
const status = await validateAll({ rules, updates });
const valid = status.filter(({ isValid }) => isValid)
.map(({ item }) => item);
const result = calculate(valid);
return result;
};
const validateAll: GetFn = async ({ rules, updates }) => {
const status: Array<ValidityStatus> = [];
for (const item of updates) {
let isValid = true;
const tasks = item.map(
(_, i) => validate(i, item, rules).catch(() => isValid = false)
);
await Promise.all(tasks);
status.push({ item, isValid });
}
return status;
};
const validate: ValidateFn = async (index, update, rules) => {
const promise = new Promise<boolean>(async (resolve, reject) => {
setTimeout(() => {
const successors = rules[update[index]] ?? [];
if (successors.length == 0) { resolve(true); }
const prev = update.slice(0, index);
for (const item of prev) {
if (successors.indexOf(item) >= 0) { return reject(); }
}
resolve(true);
});
});
return promise;
};
const calculate: CalculateFn = (update) => {
let result = 0;
for (const item of update) {
const mid = Math.floor(item.length / 2);
result += item[mid];
}
return result;
};
const solution: Fn = async ({ rules, updates }) => {
// check part 1 for validateAll definition
const status = await validateAll({ rules, updates });
const invalid = status.filter(({ isValid }) => !isValid)
.map(({ item }) => item);
const valid = await applyRulesAll(invalid, rules);
// check part 1 for calculate definition
const result = calculate(valid);
return result;
};
const applyRulesAll: ApplyAllFn = async (updates, rules) => {
const tasks = updates.map((item) => applyRules(item, rules));
const result = await Promise.all(tasks);
return result;
}
const applyRules: ApplyFn = (update, rules) => {
const promise = new Promise<Array<number>>(async (resolve) => {
setTimeout(() => {
let latest = update;
for (let i = 0; i < update.length; i++) {
const successors = rules[update[i]] ?? [];
if (successors.length == 0) { continue; }
const prev = latest.slice(0, i);
const current = latest[i];
const newPrev: Array<number> = [];
const newNext = latest.slice(i + 1);
for (let j = prev.length - 1; j >= 0; j--) {
const item = prev[j];
if (successors.indexOf(item) >= 0) {
newNext.unshift(item);
} else {
newPrev.unshift(item);
}
}
latest = [...newPrev, current, ...newNext];
}
resolve(latest);
});
});
return promise;
}