From e9510af19280f4a45ff58b6ec9515d9f9e6f762f Mon Sep 17 00:00:00 2001 From: lukasbicus Date: Tue, 1 Oct 2024 14:22:14 +0200 Subject: [PATCH 1/8] Add day17 puzzle1 with inputs --- scripts/aoc2015/day17/input.txt | 20 ++++++++++ scripts/aoc2015/day17/puzzle1.ts | 55 +++++++++++++++++++++++++++ scripts/aoc2015/day17/simpleInput.txt | 5 +++ 3 files changed, 80 insertions(+) create mode 100644 scripts/aoc2015/day17/input.txt create mode 100644 scripts/aoc2015/day17/puzzle1.ts create mode 100644 scripts/aoc2015/day17/simpleInput.txt diff --git a/scripts/aoc2015/day17/input.txt b/scripts/aoc2015/day17/input.txt new file mode 100644 index 0000000..e87da5f --- /dev/null +++ b/scripts/aoc2015/day17/input.txt @@ -0,0 +1,20 @@ +33 +14 +18 +20 +45 +35 +16 +35 +1 +13 +18 +13 +50 +44 +48 +6 +24 +41 +30 +42 \ No newline at end of file diff --git a/scripts/aoc2015/day17/puzzle1.ts b/scripts/aoc2015/day17/puzzle1.ts new file mode 100644 index 0000000..8257e89 --- /dev/null +++ b/scripts/aoc2015/day17/puzzle1.ts @@ -0,0 +1,55 @@ +/* +--- 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? + + + */ + +// ALGORITHM + +// read file +// parse containers - fill array of containers + +// create iterator based on available containers + +// filter out combinations of containers with size 150l + +// 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] diff --git a/scripts/aoc2015/day17/simpleInput.txt b/scripts/aoc2015/day17/simpleInput.txt new file mode 100644 index 0000000..4556764 --- /dev/null +++ b/scripts/aoc2015/day17/simpleInput.txt @@ -0,0 +1,5 @@ +20 +15 +10 +5 +5 \ No newline at end of file From c50f7c9d03da9f70ed04c1f98be5d3d1a2feaf34 Mon Sep 17 00:00:00 2001 From: lukasbicus Date: Tue, 1 Oct 2024 14:35:42 +0200 Subject: [PATCH 2/8] Implement parseContainerLine --- scripts/aoc2015/day17/utils.test.ts | 14 ++++++++++++++ scripts/aoc2015/day17/utils.ts | 6 ++++++ 2 files changed, 20 insertions(+) create mode 100644 scripts/aoc2015/day17/utils.test.ts create mode 100644 scripts/aoc2015/day17/utils.ts diff --git a/scripts/aoc2015/day17/utils.test.ts b/scripts/aoc2015/day17/utils.test.ts new file mode 100644 index 0000000..006c597 --- /dev/null +++ b/scripts/aoc2015/day17/utils.test.ts @@ -0,0 +1,14 @@ +import { assertEquals } from "@std/assert"; +import { describe, it } from "@std/testing/bdd"; +import { 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); + }); +}); diff --git a/scripts/aoc2015/day17/utils.ts b/scripts/aoc2015/day17/utils.ts new file mode 100644 index 0000000..598edda --- /dev/null +++ b/scripts/aoc2015/day17/utils.ts @@ -0,0 +1,6 @@ +const containerRegex = /(\d+)/; + +export function parseContainerLine(line: string): number | null { + const match = line.match(containerRegex); + return match ? parseInt(match[1]) : null; +} From 54178bf67a7fd7f06c09f7c6c22241e9967d8e9d Mon Sep 17 00:00:00 2001 From: lukasbicus Date: Tue, 1 Oct 2024 14:48:29 +0200 Subject: [PATCH 3/8] Write simple tests. --- scripts/aoc2015/day17/puzzle1.ts | 32 ------------------------ scripts/aoc2015/day17/utils.test.ts | 28 ++++++++++++++++++++- scripts/aoc2015/day17/utils.ts | 38 +++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 33 deletions(-) diff --git a/scripts/aoc2015/day17/puzzle1.ts b/scripts/aoc2015/day17/puzzle1.ts index 8257e89..2b35a7c 100644 --- a/scripts/aoc2015/day17/puzzle1.ts +++ b/scripts/aoc2015/day17/puzzle1.ts @@ -21,35 +21,3 @@ Filling all containers entirely, how many different combinations of containers c // create iterator based on available containers // filter out combinations of containers with size 150l - -// 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] diff --git a/scripts/aoc2015/day17/utils.test.ts b/scripts/aoc2015/day17/utils.test.ts index 006c597..1208320 100644 --- a/scripts/aoc2015/day17/utils.test.ts +++ b/scripts/aoc2015/day17/utils.test.ts @@ -1,6 +1,9 @@ import { assertEquals } from "@std/assert"; import { describe, it } from "@std/testing/bdd"; -import { parseContainerLine } from "./utils.ts"; +import { + generateCombinationsWithoutRepetition, + parseContainerLine, +} from "./utils.ts"; describe("parseContainerLine", function () { it("should return null for invalid line", function () { @@ -12,3 +15,26 @@ describe("parseContainerLine", function () { 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 1", function () { + const expectedResult = [[], ["a"], ["b"], ["a", "b"]]; + const result = [...generateCombinationsWithoutRepetition(["a", "b"])]; + assertEquals(result, expectedResult); + }); +}); diff --git a/scripts/aoc2015/day17/utils.ts b/scripts/aoc2015/day17/utils.ts index 598edda..077ade5 100644 --- a/scripts/aoc2015/day17/utils.ts +++ b/scripts/aoc2015/day17/utils.ts @@ -4,3 +4,41 @@ 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( + items: T[], +): Generator { + yield [] as T[]; +} From 0f1e2fcab3ef01aeda5bb44a1bddf4a7481d9747 Mon Sep 17 00:00:00 2001 From: lukasbicus Date: Tue, 1 Oct 2024 14:56:22 +0200 Subject: [PATCH 4/8] Write more complex test for 3 items. --- scripts/aoc2015/day17/utils.test.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/scripts/aoc2015/day17/utils.test.ts b/scripts/aoc2015/day17/utils.test.ts index 1208320..0f899d5 100644 --- a/scripts/aoc2015/day17/utils.test.ts +++ b/scripts/aoc2015/day17/utils.test.ts @@ -32,9 +32,24 @@ describe("generateCombinationsWithoutRepetition", function () { assertEquals(result, expectedResult); }); - it("should return 4 results, if length of input items is 1", function () { + 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"], + ["a", "c"], + ["c"], + ["b", "c"], + ["a", "b", "c"], + ]; + const result = [...generateCombinationsWithoutRepetition(["a", "b", "c"])]; + assertEquals(result, expectedResult); + }); }); From 23d6115bd4801512cefeb09c2da4317ec57ff82d Mon Sep 17 00:00:00 2001 From: lukasbicus Date: Tue, 1 Oct 2024 15:03:59 +0200 Subject: [PATCH 5/8] Implement generateCombinationsWithoutRepetition, fix tests. --- scripts/aoc2015/day17/utils.test.ts | 2 +- scripts/aoc2015/day17/utils.ts | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/aoc2015/day17/utils.test.ts b/scripts/aoc2015/day17/utils.test.ts index 0f899d5..65c279f 100644 --- a/scripts/aoc2015/day17/utils.test.ts +++ b/scripts/aoc2015/day17/utils.test.ts @@ -44,8 +44,8 @@ describe("generateCombinationsWithoutRepetition", function () { ["a"], ["b"], ["a", "b"], - ["a", "c"], ["c"], + ["a", "c"], ["b", "c"], ["a", "b", "c"], ]; diff --git a/scripts/aoc2015/day17/utils.ts b/scripts/aoc2015/day17/utils.ts index 077ade5..b839341 100644 --- a/scripts/aoc2015/day17/utils.ts +++ b/scripts/aoc2015/day17/utils.ts @@ -40,5 +40,18 @@ export function parseContainerLine(line: string): number | null { export function* generateCombinationsWithoutRepetition( items: T[], ): Generator { - yield [] as 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); + } + } } From 476cab37fe276c1e1a42ba9f3cfc44144a2200a7 Mon Sep 17 00:00:00 2001 From: lukasbicus Date: Tue, 1 Oct 2024 15:12:49 +0200 Subject: [PATCH 6/8] Solve puzzle1. --- scripts/aoc2015/day17/puzzle1.ts | 44 +++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/scripts/aoc2015/day17/puzzle1.ts b/scripts/aoc2015/day17/puzzle1.ts index 2b35a7c..9807f79 100644 --- a/scripts/aoc2015/day17/puzzle1.ts +++ b/scripts/aoc2015/day17/puzzle1.ts @@ -15,9 +15,41 @@ Filling all containers entirely, how many different combinations of containers c // ALGORITHM -// read file -// parse containers - fill array of containers - -// create iterator based on available containers - -// filter out combinations of containers with size 150l +import { + generateCombinationsWithoutRepetition, + parseContainerLine, +} from "./utils.ts"; + +async function processFile( + filename: string, + amountWanted: number, +): Promise { + // 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 +} + +processFile("simpleInput.txt", 25); +processFile("input.txt", 150); From 3b2805dd19f7b1b26ad8f887564522317e8da6b7 Mon Sep 17 00:00:00 2001 From: lukasbicus Date: Tue, 1 Oct 2024 15:28:40 +0200 Subject: [PATCH 7/8] Add algorithm for puzzle2 --- scripts/aoc2015/day17/puzzle1.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/aoc2015/day17/puzzle1.ts b/scripts/aoc2015/day17/puzzle1.ts index 9807f79..6ff2afd 100644 --- a/scripts/aoc2015/day17/puzzle1.ts +++ b/scripts/aoc2015/day17/puzzle1.ts @@ -10,6 +10,12 @@ For example, suppose you have containers of size 20, 15, 10, 5, and 5 liters. If 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. */ @@ -49,6 +55,13 @@ async function processFile( 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 + + // find the count of combinations with the shortest length } processFile("simpleInput.txt", 25); From 2db26d67e187ab64466fa8a1a0184c19a385f109 Mon Sep 17 00:00:00 2001 From: lukasbicus Date: Wed, 2 Oct 2024 09:31:34 +0200 Subject: [PATCH 8/8] Solve puzzle2 --- scripts/aoc2015/day17/puzzle1.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/aoc2015/day17/puzzle1.ts b/scripts/aoc2015/day17/puzzle1.ts index 6ff2afd..61e2543 100644 --- a/scripts/aoc2015/day17/puzzle1.ts +++ b/scripts/aoc2015/day17/puzzle1.ts @@ -60,8 +60,19 @@ async function processFile( // 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);