Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions scripts/aoc2015/day17/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
33
14
18
20
45
35
16
35
1
13
18
13
50
44
48
6
24
41
30
42
79 changes: 79 additions & 0 deletions scripts/aoc2015/day17/puzzle1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
--- Day 17: No Such Thing as Too Much ---
The elves bought too much eggnog again - 150 liters this time. To fit it all into your refrigerator, you'll need to move it into smaller containers. You take an inventory of the capacities of the available containers.

For example, suppose you have containers of size 20, 15, 10, 5, and 5 liters. If you need to store 25 liters, there are four ways to do it:

15 and 10
20 and 5 (the first 5)
20 and 5 (the second 5)
15, 5, and 5
Filling all containers entirely, how many different combinations of containers can exactly fit all 150 liters of eggnog?

--- Part Two ---
While playing with all the containers in the kitchen, another load of eggnog arrives! The shipping and receiving department is requesting as many containers as you can spare.

Find the minimum number of containers that can exactly fit all 150 liters of eggnog. How many different ways can you fill that number of containers and still hold exactly 150 litres?

In the example above, the minimum number of containers was two. There were three ways to use that many containers, and so the answer there would be 3.

*/

// ALGORITHM

import {
generateCombinationsWithoutRepetition,
parseContainerLine,
} from "./utils.ts";

async function processFile(
filename: string,
amountWanted: number,
): Promise<void> {
// read file
const input = await Deno.readTextFile(filename);
const containers: number[] = [];
for (const line of input.split("\n")) {
// parse containers - fill array of containers
const container = parseContainerLine(line);
if (container) {
containers.push(container);
}
}
// create iterator based on available containers
const combinations: number[][] = [];
for (
const combination of generateCombinationsWithoutRepetition(containers)
) {
if (
combination.reduce((acc, container) => acc + container, 0) ===
amountWanted
) {
combinations.push(combination);
}
}
console.log("combinations count", combinations.length);

// filter out combinations of containers with size 150l

// puzzle 2

// find the combination with shortest length
// create array of combination lengths, find min
const theSmallestCountOfContainers = Math.min(
...combinations.map((combination) => combination.length),
);

// find the count of combinations with the shortest length
const count =
combinations.filter((combination) =>
combination.length === theSmallestCountOfContainers
).length;
console.log(
"count of combinations with the smallest count of containers",
count,
);
}

processFile("simpleInput.txt", 25);
processFile("input.txt", 150);
5 changes: 5 additions & 0 deletions scripts/aoc2015/day17/simpleInput.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
20
15
10
5
5
55 changes: 55 additions & 0 deletions scripts/aoc2015/day17/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { assertEquals } from "@std/assert";
import { describe, it } from "@std/testing/bdd";
import {
generateCombinationsWithoutRepetition,
parseContainerLine,
} from "./utils.ts";

describe("parseContainerLine", function () {
it("should return null for invalid line", function () {
assertEquals(parseContainerLine("invalid line"), null);
});

it("should return null for valid line", function () {
assertEquals(parseContainerLine("5"), 5);
assertEquals(parseContainerLine("25"), 25);
});
});

describe("generateCombinationsWithoutRepetition", function () {
it("should return an empty array, if length of input items is 0", function () {
const generator = generateCombinationsWithoutRepetition([]);
const result = generator.next();
assertEquals(result, {
value: [],
done: false,
});
});

it("should return 2 results, if length of input items is 1", function () {
const expectedResult = [[], ["a"]];
const result = [...generateCombinationsWithoutRepetition(["a"])];
assertEquals(result, expectedResult);
});

it("should return 4 results, if length of input items is 2", function () {
const expectedResult = [[], ["a"], ["b"], ["a", "b"]];
const result = [...generateCombinationsWithoutRepetition(["a", "b"])];
assertEquals(result, expectedResult);
});

it("should return 8 results, if length of input items is 3", function () {
const expectedResult = [
[],
["a"],
["b"],
["a", "b"],
["c"],
["a", "c"],
["b", "c"],
["a", "b", "c"],
];
const result = [...generateCombinationsWithoutRepetition(["a", "b", "c"])];
assertEquals(result, expectedResult);
});
});
57 changes: 57 additions & 0 deletions scripts/aoc2015/day17/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const containerRegex = /(\d+)/;

export function parseContainerLine(line: string): number | null {
const match = line.match(containerRegex);
return match ? parseInt(match[1]) : null;
}

// getCombinationsWithoutRepetition

// for set of items {a, b}, available combinations are:
// []
// [a]
// [b]
// [a, b]

// for set of items {a, b, c}, available combinations are:
// []
// [a]
// [b]
// [c]
// [a, b]
// [a, c]
// [b, c]
// [a, b, c]

// those can be grouped into:

// without item "a"
// []
// [b]
// [c]
// [b, c]

// with item "a"- see - the item "a" is added in front of all options without "a"
// [a]
// [a, b]
// [a, c]
// [a, b, c]

export function* generateCombinationsWithoutRepetition<T>(
items: T[],
): Generator<T[]> {
if (items.length === 0) {
yield [];
return;
} else if (items.length === 1) {
yield [];
yield [items[0]];
// items.length > 1
} else {
const firstItem = items.shift() as T;
for (const combination of generateCombinationsWithoutRepetition(items)) {
yield combination;
yield [firstItem].concat(combination);
}
}
}
Loading