Skip to content

Commit

Permalink
fixing up day 5 and writeups
Browse files Browse the repository at this point in the history
  • Loading branch information
CodingAP committed Dec 6, 2023
1 parent d35cc1f commit 11e2608
Show file tree
Hide file tree
Showing 12 changed files with 7,769 additions and 5,789 deletions.
2 changes: 1 addition & 1 deletion aoc/puzzles/2023/day05/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
|| **Part 1** | **Part 2** |
|:--:|:---:|:---:|
| **Results** | 484023871 | 46294175 |
| **Time (in ms)** | 0.43 | TOO LONG!!! |
| **Time (in ms)** | 0.56 | 24.78 |
136 changes: 95 additions & 41 deletions aoc/puzzles/2023/day05/solution.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* this is my solution for this advent of code puzzle
*
* by alex prosser
* 12/4/2023
* 12/6/2023
*/

/**
Expand All @@ -15,34 +15,44 @@
* @returns {Promise<string | number>} the result of part 1
*/
const part1 = async input => {
let [seeds, ...maps] = input.split(/\n\n/g);
// seperate each group for parsing
let groups = input.split(/\n\n/g);

seeds = seeds.split(/: /)[1].split(/ /g).map(num => parseInt(num));
maps = maps.reduce((obj, map) => {
/**
* seed numbers from input
*
* @type {number[]}
*/
let seeds = groups[0].split(/: /)[1].split(/ /g).map(num => parseInt(num));

/**
* mapping between ids
*
* @type {Record<string, { destStart: number, sourceStart: number, range: number }[]>}
*/
const maps = groups.slice(1).reduce((obj, map) => {
let [name, ...locations] = map.split(/\n/g);
obj[name.split(/ /)[0]] = locations.map(numbers => numbers.split(/ /).map(num => parseInt(num)));
obj[name.split(/ /)[0]] = locations.map(numbers => {
let [destStart, sourceStart, range] = numbers.split(/ /g).map(num => parseInt(num));
return { destStart, sourceStart, range }
});
return obj;
}, {});

let mapNames = Object.keys(maps);

let source = seeds;
for (let i = 0; i < mapNames.length; i++) {
let destination = maps[mapNames[i]];

for (let i = 0; i < source.length; i++) {
let newNumber = source[i];
for (let j = 0; j < destination.length; j++) {
if (newNumber >= destination[j][1] && newNumber <= destination[j][1] + destination[j][2]) {
newNumber = (newNumber - destination[j][1]) + destination[j][0];
break;
// map each seed number to the mapping defined in the input
Object.values(maps).forEach(mapping => {
seeds = seeds.map(seed => {
for (let i = 0; i < mapping.length; i++) {
if (seed >= mapping[i].sourceStart && seed <= mapping[i].sourceStart + mapping[i].range) {
return (seed - mapping[i].sourceStart) + mapping[i].destStart;
}
}
source[i] = newNumber;
}
}
return seed;
});
});

return source.reduce((min, num) => Math.min(min, num), Infinity);
// find the smallest seed number after all the mappings
return seeds.reduce((min, num) => Math.min(min, num), Infinity);
}

/**
Expand All @@ -52,39 +62,83 @@ const part1 = async input => {
* @returns {Promise<string | number>} the result of part 2
*/
const part2 = async input => {
let [seeds, ...maps] = input.split(/\n\n/g);
// seperate each group for parsing
let groups = input.split(/\n\n/g);

seeds = seeds.split(/: /)[1].split(/ /g).map(num => parseInt(num));
/**
* seed numbers from input
*
* @type {number[]}
*/
let seeds = groups[0].split(/: /)[1].split(/ /g).map(num => parseInt(num));

maps = maps.reduce((obj, map) => {
/**
* mapping between ids
*
* @type {Record<string, { destStart: number, sourceStart: number, range: number }[]>}
*/
const maps = groups.slice(1).reduce((obj, map) => {
let [name, ...locations] = map.split(/\n/g);
obj[name.split(/ /)[0]] = locations.map(numbers => numbers.split(/ /).map(num => parseInt(num)));
obj[name.split(/ /)[0]] = locations.map(numbers => {
let [destStart, sourceStart, range] = numbers.split(/ /g).map(num => parseInt(num));
return { destStart, sourceStart, range }
});
return obj;
}, {});

const mapNames = Object.keys(maps);

/**
* find the smallest id of the entire range using range intersectioms
*
* @param {{ start: number, end: number }} range the range to be mapped
*/
const findMinimum = range => {
let min = Infinity;
for (let num = range.start; num < range.end; num++) {
let newNumber = num;
for (let i = 0; i < mapNames.length; i++) {
let destination = maps[mapNames[i]];
for (let j = 0; j < destination.length; j++) {
if (newNumber >= destination[j][1] && newNumber <= destination[j][1] + destination[j][2]) {
newNumber = (newNumber - destination[j][1]) + destination[j][0];
break;
let unmapped = [structuredClone(range)], mapped = [];

// go through all mappings to map the entire range
Object.values(maps).forEach(mapping => {
// go through mappings first, then map each range
// putting mapped ranges in 'mapped' and unmapped in 'unmapped' to keep attempting to map
for (let i = 0; i < mapping.length; i++) {
let mappingRange = { start: mapping[i].sourceStart, end: mapping[i].sourceStart + mapping[i].range };
let newUnmapped = [];
unmapped.map(range => {
// check for range collision
if (range.start <= mappingRange.end && range.end >= mappingRange.start) {
// cutoff starting overlap if there
if (range.start < mappingRange.start) {
newUnmapped.push({ start: range.start, end: mappingRange.start - 1 });
}

// cutoff ending overlap if there
if (range.end > mappingRange.end) {
newUnmapped.push({ start: mappingRange.end, end: range.end - 1 });
}

// map the rest of the range
let mappedStart = (Math.max(range.start, mappingRange.start) - mapping[i].sourceStart) + mapping[i].destStart;
let mappedEnd = (Math.min(range.end, mappingRange.end) - mapping[i].sourceStart) + mapping[i].destStart;
mapped.push({ start: mappedStart, end: mappedEnd });
} else {
newUnmapped.push(structuredClone(range));
}
}
});

// set unmapped to all the created ones
unmapped = structuredClone(newUnmapped);
}
min = Math.min(min, newNumber);
}
return min;

// reset mapped and unmapped
unmapped = [...structuredClone(mapped), ...structuredClone(unmapped)];
mapped = [];
});

return unmapped.reduce((min, range) => Math.min(min, range.start), Infinity);
}

// find the smallest of all the ranges
let min = Infinity;
for (let i = 0; i < seeds.length; i += 2) {
min = Math.min(min, findMinimum({ start: seeds[i], end: seeds[i] + seeds[i + 1] }));
min = Math.min(min, findMinimum({ start: seeds[i], end: seeds[i] + seeds[i + 1] - 1 }));
}
return min;
}
Expand Down
17 changes: 17 additions & 0 deletions aoc/writeups/2023/day05.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Leaderboard Positions - **Part 1**: 1214, **Part 2**: 3999

Holy hell! I wish I can go out on a limb and say that was the hardest puzzle of the year, but it was only Day 5 :(.

For this puzzle, we are given a mapping of seeds to soil to fertilizer to blah blah blah. It doesn't matter about what names they map to, we just have to map seed numbers 7 times using the ranges defined in the input. For part 1, we take the `seeds` list at the top of the input, go through all the mappings, and find the smallest value. To do this, we can simply go through all the mapping's ranges, see if the seed number if between it; if it is, then we map the seed number and continue with the next. If no range is found, we leave it be. We do this process for each mapping and we are left with 7-mapped numbers that we can find the minimum of. For part 2, we treat those list of seed numbers as two digits per entry: one is the start, the second is the range. For example...

```
[79] [14] [55] [13]
is now
[79 14] [55 13]
```

Theses ranges are also treated like `[79, 93)` (`79 + 14 = 93`), so 93 doesn't get mapped in this first range. If you look at my code, I just subtract 1 from all the ends and it seemed to work (probably a more elegant way to handle it). So when we go through all the mappings this time, I separated the ranges between `mapped` and `unmapped`. All the `unmapped` are checked for any range collisions; if they do collide, split the ranges so that only the numbers in the mapping range get mapped, and continue. This allows us to turn this billion-operation problem into a few thousand, which the computer can handle easily.

*NOTE: I originally went with a brute force solution the night of the puzzle's opening, and I was lucky to find the minimum in the second range of seed numbers, so I didn't have to run my solution for hours.*

I think that I will look back at this puzzle because it was harder than most of 2020 and 2015 (the ones that I have redone to train for 2023) and it is ONLY DAY 5!!! Until then, I look forward to the rest of 2023.
11 changes: 11 additions & 0 deletions aoc/writeups/2023/day06.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Leaderboard Positions - **Part 1**: 303, **Part 2**: 178

It seems to be that the even days are the easier problems and the odd days are the harder problems (with the even days getting easier and the odd days get harder). I did absolutely wonderful this day, the best I did so far, but it makes me wary of the Day 7 (oh no).

Anyways, for this puzzle we need to see which of our boats beats the record distances given to us based on how long we hold on to the accelerator. For example, if our time is `15 seconds` and our record distance of `40 units`. We can hold it for `7 seconds`, which allows the boat to go at `7 units/sec`, but then we only have `8 seconds` to race. That will allow it to go `56 units (7 units/sec * 8 sec)`, which beats the record.

For part 1, we need to go through all pairs of times and distances; for each we need to find how many ways we can beat the record and then multiply them all together. This just consists of doing a for loop on each pair that checks if `i * (time - i)` is greater than the record. Since the numbers are very small (especially compared to Day 5), this is really fast.

For part 2, we do the same thing except we combine our numbers in the input. This was a very simple process, and the same procedure works. Doing 50 million operations is still pretty fast, so I only changed the parsing.

This is a fun break after dealing with the headache that was Day 5, but as mentioned before, I am scared of what Day 7 has to offer.
10,607 changes: 4,958 additions & 5,649 deletions index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion writeups/2015/day01/index.html

Large diffs are not rendered by default.

460 changes: 436 additions & 24 deletions writeups/2023/day01/index.html

Large diffs are not rendered by default.

458 changes: 434 additions & 24 deletions writeups/2023/day02/index.html

Large diffs are not rendered by default.

457 changes: 433 additions & 24 deletions writeups/2023/day03/index.html

Large diffs are not rendered by default.

463 changes: 438 additions & 25 deletions writeups/2023/day04/index.html

Large diffs are not rendered by default.

Loading

0 comments on commit 11e2608

Please sign in to comment.