From 79e994e9e8b1e6a2cdb64a9a16e59feefff95cf6 Mon Sep 17 00:00:00 2001 From: Thijs Busser Date: Mon, 25 Nov 2024 21:42:06 +0100 Subject: [PATCH] Add solution for 2015, day 20 --- 2015/20/README.md | 33 +++++++++++++++++++++++ 2015/20/helpers/find-factors.test.ts | 22 +++++++++++++++ 2015/20/helpers/find-factors.ts | 40 ++++++++++++++++++++++++++++ 2015/20/part-1.ts | 28 +++++++++++++++++++ 2015/20/part-2.ts | 31 +++++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 2015/20/README.md create mode 100644 2015/20/helpers/find-factors.test.ts create mode 100644 2015/20/helpers/find-factors.ts create mode 100644 2015/20/part-1.ts create mode 100644 2015/20/part-2.ts diff --git a/2015/20/README.md b/2015/20/README.md new file mode 100644 index 0000000..33fa912 --- /dev/null +++ b/2015/20/README.md @@ -0,0 +1,33 @@ +# Day 20: Infinite Elves and Infinite Houses +To keep the Elves busy, Santa has them deliver some presents by hand, door-to-door. He sends them down a street with infinite houses numbered sequentially: `1`, `2`, `3`, `4`, `5`, and so on. + +Each Elf is assigned a number, too, and delivers presents to houses based on that number: + +- The first Elf (number `1`) delivers presents to every house: `1`, `2`, `3`, `4`, `5`, .... +- The second Elf (number `2`) delivers presents to every second house: `2`, `4`, `6`, `8`, `10`, .... +- Elf number `3` delivers presents to every third house: `3`, `6`, `9`, `12`, `15`, .... + +There are infinitely many Elves, numbered starting with `1`. Each Elf delivers presents equal to **ten times** his or her number at each house. + +So, the first nine houses on the street end up like this: + +``` +House 1 got 10 presents. +House 2 got 30 presents. +House 3 got 40 presents. +House 4 got 70 presents. +House 5 got 60 presents. +House 6 got 120 presents. +House 7 got 80 presents. +House 8 got 150 presents. +House 9 got 130 presents. +``` + +The first house gets `10` presents: it is visited only by Elf `1`, which delivers `1 * 10 = 10` presents. The fourth house gets `70` presents, because it is visited by Elves `1`, `2`, and `4`, for a total of `10 + 20 + 40 = 70` presents. + +What is the lowest house number of the house to get at least as many presents as the number in your puzzle input? + +## Part Two +The Elves decide they don't want to visit an infinite number of houses. Instead, each Elf will stop after delivering presents to `50` houses. To make up for it, they decide to deliver presents equal to **eleven times** their number at each house. + +With these changes, what is the new **lowest house number** of the house to get at least as many presents as the number in your puzzle input? \ No newline at end of file diff --git a/2015/20/helpers/find-factors.test.ts b/2015/20/helpers/find-factors.test.ts new file mode 100644 index 0000000..b041332 --- /dev/null +++ b/2015/20/helpers/find-factors.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'vitest'; + +import { findFactors } from './find-factors.js'; + +/* ========================================================================== */ + +describe('Calculate factors', () => { + it('should return the factors for any given number', () => { + expect(findFactors(25)).toEqual([1, 5, 25]); + expect(findFactors(45)).toEqual([1, 3, 5, 9, 15, 45]); + expect(findFactors(53)).toEqual([1, 53]); + expect(findFactors(64)).toEqual([1, 2, 4, 8, 16, 32, 64]); + expect(findFactors(100)).toEqual([1, 2, 4, 5, 10, 20, 25, 50, 100]); + expect(findFactors(102)).toEqual([1, 2, 3, 6, 17, 34, 51, 102]); + expect(findFactors(120)).toEqual([1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120]); + expect(findFactors(12345)).toEqual([1, 3, 5, 15, 823, 2469, 4115, 12345]); + expect(findFactors(32766)).toEqual([ + 1, 2, 3, 6, 43, 86, 127, 129, 254, 258, 381, 762, 5461, 10922, 16383, 32766 + ]); + expect(findFactors(32767)).toEqual([1, 7, 31, 151, 217, 1057, 4681, 32767]); + }); +}); diff --git a/2015/20/helpers/find-factors.ts b/2015/20/helpers/find-factors.ts new file mode 100644 index 0000000..f1fcfda --- /dev/null +++ b/2015/20/helpers/find-factors.ts @@ -0,0 +1,40 @@ +/** + * Finds the factors for a given number. + * + * @param value The number for which to find the the factors. + * + * @returns An array with all the factors, sorted from low to high. + * + * @see {@link https://courses.lumenlearning.com/mathforliberalartscorequisite/chapter/finding-all-the-factors-of-a-number/} + */ +export function findFactors(value: number): number[] { + const factors: number[] = []; + // We need to stop when the divisor becomes smaller than the quotient. We + // could do that be checking the result in the for loop or we calculate when + // it is. By taking the square root we know the tipping point and since we + // only deal with integers we need to round it down. + // E.g.: When factoring 72 the tipping point is 8. This because the square + // root of 72, rounded down, is 8. + // - 72 / 8 = 9, the divisor (8) is more than the quotient (9) + // - 72 / 9 = 8, the divisor (9) has become more than the quotient (8) + const limit = Math.floor(Math.sqrt(value)); + + // Starting by 1 keep processing all the integers until the limit has been + // processed too. + for (let divisor = 1; divisor <= limit; divisor++) { + // When the quotient is not a whole number, the divisor and quotient + // are not factors. + if (value % divisor !== 0) continue; + + factors.push(divisor); + + // When the divisor and quotient are the same, there is no need to add + // the quotient the list of factors it has already been added when the + // divisor was added to the list. + if (value / divisor !== divisor) { + factors.push(value / divisor); + } + } + + return factors.sort((a, b) => a - b); +} diff --git a/2015/20/part-1.ts b/2015/20/part-1.ts new file mode 100644 index 0000000..dd38415 --- /dev/null +++ b/2015/20/part-1.ts @@ -0,0 +1,28 @@ +import { findFactors } from './helpers/find-factors.js'; + +/* ========================================================================== */ + +async function solver(input: string): Promise { + // Each elf gives 10 times the number of presents as his/her number. If we + // divide the input by 10 each elf gives 1 time the number of presents as + // his/her number and we a lower target to find a solution to. + const presentsGoal = Number(input) / 10; + + // Iterate over the houses, start with 1 house and keep increasing till the + // first house with the specified number of presents has been found. + for (let houseNumber = 1; houseNumber < Infinity; houseNumber++) { + const visitingElves = findFactors(houseNumber); + const numberOfPresents = visitingElves.reduce((sum, count) => sum + count, 0); + + if (numberOfPresents >= presentsGoal) return houseNumber; + } + + return -1; +} + +/* ========================================================================== */ + +export default { + prompt: 'lowest house number to receive specified number of presents', + solver +} satisfies Solution; diff --git a/2015/20/part-2.ts b/2015/20/part-2.ts new file mode 100644 index 0000000..aa64e7f --- /dev/null +++ b/2015/20/part-2.ts @@ -0,0 +1,31 @@ +import { findFactors } from './helpers/find-factors.js'; + +/* ========================================================================== */ + +async function solver(input: string): Promise { + const presentsGoal = Number(input); + + // Iterate over the houses, start with 1 house and keep increasing till the + // first house with the specified number of presents has been found. + for (let houseNumber = 1; houseNumber < Infinity; houseNumber++) { + // Get the number of the elves that will make a stop at the + // current house. Only elves for whom it is at most their fifth visit + // will visit this house. Elves which have already visited 50 houses + // will sit this one out. + const visitingElves = findFactors(houseNumber).filter(elf => houseNumber / elf <= 50); + + // Count the number of presents which will be presented to the house. + const numberOfPresents = visitingElves.reduce((sum, elf) => sum + (elf * 11), 0); + + if (numberOfPresents >= presentsGoal) return houseNumber; + } + + return -1; +} + +/* ========================================================================== */ + +export default { + prompt: 'lowest house number to receive specified number of presents', + solver +} satisfies Solution;