Skip to content

Commit

Permalink
Add solution for 2015, day 20
Browse files Browse the repository at this point in the history
  • Loading branch information
tbusser committed Nov 25, 2024
1 parent 882e167 commit 79e994e
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 0 deletions.
33 changes: 33 additions & 0 deletions 2015/20/README.md
Original file line number Diff line number Diff line change
@@ -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?
22 changes: 22 additions & 0 deletions 2015/20/helpers/find-factors.test.ts
Original file line number Diff line number Diff line change
@@ -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]);
});
});
40 changes: 40 additions & 0 deletions 2015/20/helpers/find-factors.ts
Original file line number Diff line number Diff line change
@@ -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);
}
28 changes: 28 additions & 0 deletions 2015/20/part-1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { findFactors } from './helpers/find-factors.js';

/* ========================================================================== */

async function solver(input: string): Promise<number> {
// 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;
31 changes: 31 additions & 0 deletions 2015/20/part-2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { findFactors } from './helpers/find-factors.js';

/* ========================================================================== */

async function solver(input: string): Promise<number> {
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;

0 comments on commit 79e994e

Please sign in to comment.