feat(day_5): both exercises done
This commit is contained in:
24
src/__tests__/day_5_test.ts
Normal file
24
src/__tests__/day_5_test.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { assertEquals } from "@std/assert";
|
||||
import {
|
||||
count_all_possible_fresh_ingredients,
|
||||
count_fresh_ingredients,
|
||||
read_ingredient_database,
|
||||
} from "../exercises/day_5.ts";
|
||||
|
||||
Deno.test("Day 5 - A", async () => {
|
||||
const ingredient_db = await read_ingredient_database(
|
||||
"src/exercises/assets/day_5_test_input.txt",
|
||||
);
|
||||
const total_fresh = count_fresh_ingredients(ingredient_db);
|
||||
|
||||
assertEquals(total_fresh, 3);
|
||||
});
|
||||
|
||||
Deno.test("Day 5 - B", async () => {
|
||||
const ingredient_db = await read_ingredient_database(
|
||||
"src/exercises/assets/day_5_test_input.txt",
|
||||
);
|
||||
const total_fresh = count_all_possible_fresh_ingredients(ingredient_db);
|
||||
|
||||
assertEquals(total_fresh, 14);
|
||||
});
|
||||
1184
src/exercises/assets/day_5_input.txt
Normal file
1184
src/exercises/assets/day_5_input.txt
Normal file
File diff suppressed because it is too large
Load Diff
11
src/exercises/assets/day_5_test_input.txt
Normal file
11
src/exercises/assets/day_5_test_input.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
3-5
|
||||
10-14
|
||||
16-20
|
||||
12-18
|
||||
|
||||
1
|
||||
5
|
||||
8
|
||||
11
|
||||
17
|
||||
32
|
||||
118
src/exercises/day_5.ts
Normal file
118
src/exercises/day_5.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
interface IngredientDB {
|
||||
fresh_ranges: { init: number; end: number }[];
|
||||
ingredient_list: number[];
|
||||
}
|
||||
|
||||
export default async function Cafeteria() {
|
||||
const ingredient_db = await read_ingredient_database(
|
||||
"src/exercises/assets/day_5_input.txt",
|
||||
);
|
||||
console.log(">> Total fresh: ", count_fresh_ingredients(ingredient_db));
|
||||
console.log(
|
||||
">> Total available fresh: ",
|
||||
count_all_possible_fresh_ingredients(ingredient_db),
|
||||
);
|
||||
// console.log(
|
||||
// ">> Total available fresh brute: ",
|
||||
// count_all_possible_fresh_ingredients_force(ingredient_db),
|
||||
// );
|
||||
}
|
||||
|
||||
// NOTE: brute force by memory
|
||||
export function count_all_possible_fresh_ingredients_force(
|
||||
db: IngredientDB,
|
||||
): number {
|
||||
const total_ingredients: Set<number> = new Set();
|
||||
db.fresh_ranges.forEach((range) => {
|
||||
for (let i = range.init; i <= range.end; i++) {
|
||||
total_ingredients.add(i);
|
||||
}
|
||||
});
|
||||
return total_ingredients.size;
|
||||
}
|
||||
|
||||
export function count_all_possible_fresh_ingredients(db: IngredientDB): number {
|
||||
let total_ingredients: number = 0;
|
||||
const fresh_ranges_clean = merge_fresh_ranges(db.fresh_ranges);
|
||||
|
||||
fresh_ranges_clean.forEach((range) => {
|
||||
total_ingredients += range.end - range.init + 1;
|
||||
});
|
||||
return total_ingredients;
|
||||
}
|
||||
|
||||
function merge_fresh_ranges(
|
||||
fresh_ranges: IngredientDB["fresh_ranges"],
|
||||
): IngredientDB["fresh_ranges"] {
|
||||
const ranges: Array<IngredientDB["fresh_ranges"][number] | undefined> = [
|
||||
...fresh_ranges,
|
||||
];
|
||||
ranges.forEach((_) => {
|
||||
ranges.forEach((range, i) => {
|
||||
for (
|
||||
let next_range_index = 0;
|
||||
next_range_index < ranges.length;
|
||||
next_range_index++
|
||||
) {
|
||||
const next_range = ranges[next_range_index];
|
||||
if (!range || !next_range || next_range_index === i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check overlap
|
||||
if (
|
||||
(next_range.init >= range.init && next_range.init <= range.end) ||
|
||||
(next_range.end >= range.init && next_range.end <= range.end) ||
|
||||
(next_range.init <= range.init && next_range.end >= range.end)
|
||||
) {
|
||||
// merge
|
||||
range.init = Math.min(next_range.init, range.init);
|
||||
range.end = Math.max(next_range.end, range.end);
|
||||
ranges[next_range_index] = undefined;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return ranges.filter((range) => range !== undefined);
|
||||
}
|
||||
|
||||
export function count_fresh_ingredients(db: IngredientDB): number {
|
||||
let total_fresh: number = 0;
|
||||
db.ingredient_list.forEach((ingredient) => {
|
||||
db.fresh_ranges.every((range) => {
|
||||
if (range.init <= ingredient && range.end >= ingredient) {
|
||||
total_fresh += 1;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
return total_fresh;
|
||||
}
|
||||
|
||||
export async function read_ingredient_database(
|
||||
path: string,
|
||||
): Promise<IngredientDB> {
|
||||
const ingredient_db: IngredientDB = { fresh_ranges: [], ingredient_list: [] };
|
||||
|
||||
const input_txt = await Deno.readTextFile(path);
|
||||
const input_divided = input_txt.split("\n\n");
|
||||
|
||||
for (const range of input_divided[0].split("\n")) {
|
||||
const range_divided = range.split("-");
|
||||
ingredient_db.fresh_ranges.push({
|
||||
init: parseInt(range_divided[0]),
|
||||
end: parseInt(range_divided[1]),
|
||||
});
|
||||
}
|
||||
|
||||
for (const ingredient of input_divided[1].split("\n")) {
|
||||
if (ingredient?.length) {
|
||||
ingredient_db.ingredient_list.push(parseInt(ingredient));
|
||||
}
|
||||
}
|
||||
|
||||
return ingredient_db;
|
||||
}
|
||||
Reference in New Issue
Block a user