175 lines
4.5 KiB
TypeScript
175 lines
4.5 KiB
TypeScript
enum Indicator {
|
|
ON = "#",
|
|
OFF = ".",
|
|
}
|
|
|
|
type ButtonWiring = number[];
|
|
type Joltage = number;
|
|
|
|
interface MachineManual {
|
|
indicators: Indicator[];
|
|
button_wirings: ButtonWiring[];
|
|
joltage_requirements: Joltage[];
|
|
}
|
|
|
|
export default async function Factory() {
|
|
console.log("== Factory ==");
|
|
const manual_list = await read_machine_manuals_quick(
|
|
"src/exercises/assets/day_10_input.txt",
|
|
);
|
|
const min_presses = count_min_button_presses(manual_list);
|
|
console.log(
|
|
">> Min button presses to start: ",
|
|
min_presses,
|
|
);
|
|
}
|
|
|
|
export function count_min_button_presses(manuals: MachineManual[]): number {
|
|
let total_sum = 0;
|
|
manuals.forEach((manual, m_i) => {
|
|
const wiring_list = manual.button_wirings;
|
|
|
|
let min_presses = Infinity;
|
|
|
|
for (let size = 1; size < wiring_list.length; size++) {
|
|
const button_combinations = make_all_combinations_of_size(
|
|
wiring_list,
|
|
size,
|
|
);
|
|
button_combinations.forEach((combination) => {
|
|
// Apply combination
|
|
let pairing_indicator = manual.indicators.map((_) => Indicator.OFF);
|
|
combination.forEach((b) => {
|
|
pairing_indicator = apply_wiring_to_indicators(
|
|
b,
|
|
pairing_indicator,
|
|
);
|
|
});
|
|
|
|
// Check if valid
|
|
if (pairing_indicator.join("") === manual.indicators.join("")) {
|
|
min_presses = combination.length;
|
|
return;
|
|
}
|
|
});
|
|
|
|
if (min_presses < Infinity) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
total_sum += min_presses;
|
|
});
|
|
|
|
return total_sum;
|
|
}
|
|
|
|
function apply_wiring_to_indicators(
|
|
wiring: ButtonWiring,
|
|
indicator: Indicator[],
|
|
): Indicator[] {
|
|
return indicator.map((w, i) =>
|
|
wiring.includes(i) ? w === Indicator.ON ? Indicator.OFF : Indicator.ON : w
|
|
);
|
|
}
|
|
|
|
function make_all_combinations_of_size<T extends unknown[]>(
|
|
list: T,
|
|
size: number,
|
|
): T[] {
|
|
const binary_cap = Math.pow(2, list.length);
|
|
|
|
const result_list: T[] = [];
|
|
|
|
for (let i = 0; i < binary_cap; i++) {
|
|
const combination = i.toString(2).padStart(list.length, "0").split("");
|
|
|
|
if (
|
|
combination.reduce((sum, n) => sum + (n === "1" ? 1 : 0), 0) !== size
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
const next_l = list.map((l, i) => combination[i] === "1" ? l : null).filter(
|
|
(l) => l !== null,
|
|
);
|
|
result_list.push(next_l as T);
|
|
}
|
|
|
|
return result_list;
|
|
}
|
|
|
|
export async function read_machine_manuals(
|
|
path: string,
|
|
): Promise<MachineManual[]> {
|
|
const line_regex = /\[([.#]+)\] (.*)+ \{(.*)\}/g;
|
|
const input_txt = await Deno.readTextFile(path);
|
|
const lines = input_txt.split("\n");
|
|
|
|
const manual_list: MachineManual[] = lines.map((line) => {
|
|
const matched_line = line.matchAll(line_regex)?.toArray()?.[0];
|
|
if (matched_line && matched_line.length > 3) {
|
|
const indicators = matched_line[1].toString().split("").map((ch) =>
|
|
ch === Indicator.ON ? Indicator.ON : Indicator.OFF
|
|
);
|
|
const buttons = matched_line[2].split(" ").map((b) =>
|
|
b.replaceAll("(", "").replaceAll(")", "").split(",").map((n) =>
|
|
parseInt(n)
|
|
)
|
|
);
|
|
const joltages = matched_line[3].split(",").map((j) => parseInt(j));
|
|
return {
|
|
indicators,
|
|
button_wirings: buttons,
|
|
joltage_requirements: joltages,
|
|
};
|
|
}
|
|
return null;
|
|
}).filter((v) => v !== null);
|
|
|
|
return manual_list;
|
|
}
|
|
|
|
export async function read_machine_manuals_quick(
|
|
path: string,
|
|
): Promise<MachineManual[]> {
|
|
const input_txt = await Deno.readTextFile(path);
|
|
const lines = input_txt.split("\n");
|
|
|
|
const manual_list: MachineManual[] = [];
|
|
|
|
lines.forEach((line, line_i) => {
|
|
const manual: MachineManual = {
|
|
indicators: [],
|
|
button_wirings: [],
|
|
joltage_requirements: [],
|
|
};
|
|
line.split(" ").forEach((element) => {
|
|
if (element.includes("[")) {
|
|
manual.indicators = element.replaceAll("[", "").replaceAll("]", "")
|
|
.split("").map((e) => e as Indicator);
|
|
} else if (element.includes("{")) {
|
|
manual.joltage_requirements = element.replaceAll("{", "").replaceAll(
|
|
"}",
|
|
"",
|
|
).split(",").map((e) => parseInt(e));
|
|
} else if (element.includes("(")) {
|
|
manual.button_wirings.push(
|
|
element.replaceAll("(", "").replaceAll(")", "").split(",").map((e) =>
|
|
parseInt(e)
|
|
),
|
|
);
|
|
}
|
|
});
|
|
|
|
if (
|
|
manual.button_wirings.length > 0 &&
|
|
manual.joltage_requirements.length > 0 && manual.indicators.length > 0
|
|
) {
|
|
manual_list.push(manual);
|
|
}
|
|
});
|
|
|
|
return manual_list;
|
|
}
|