Home >Web Front-end >JS Tutorial >Historian Hysteria

Historian Hysteria

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-12-08 10:38:13771browse

Historian Hysteria

Advent of Code 2024 Day 1

Part 1

A softball to start the year off with a smile

Solving this seems simple:

Parse the input into two equal lists of numbers
Sort each list in ascending order
Compare both values at each index
Determine the absolute value after calculating the difference
Increment a tally by the absolute value

Step 1: make two lists of numbers

First, I'll make a list of 2-item lists where each item is a number:

input.split('\n').split(' ').map(Number)

Then, I'll extract the items into separate lists based on their index:

let [list1, list2] = [
  input.map((_,i) => i == 0),
  input.map((_,i) => i == 1)
]
Running it and fixing my mistakes

First mistake: chaining split.
I can't call split on an array.
I have to split inside an iterating method, like map:

input.split("\n").map(...);

Second mistake: not enough spaces.
The input contains several spaces between each number, not one:

input.split("\n").map((el) => el.split("   ").map(Number));

Third mistake: overthinking list access.

My code acted as if each nested list was one element, and returned boolean values based on whether the element was first or second in the list.

What???!!!

This code recognizes each list and keeps the first or second item:

let [list1, list2] = [
  input.map(list => list[0]),
  input.map(list => list[1]),
];

Alas, my algorithm now generates two lists of numbers!

Whew, I got a little rusty not having done these for ten months.

Sort each list in ascending order

This should be short and sweet.

In fact, I'll just append to the code directly above:

let [list1, list2] = [
  input.map(list => list[0]).sort((a,b) => a - b),
  input.map(list => list[1]).sort((a,b) => a - b),
];

Worked like a charm on the example input:

[ 1, 2, 3, 3, 3, 4 ]
[ 3, 3, 3, 4, 5, 9 ]

The other three steps, all at once!

let answer = 0;
for (let i = 0; i < list1.length; i++) {
  answer += Math.abs(list1[i] - list2[i]);
}

It works on the example: 11

Will it work on my puzzle input, though?

It does!

Woohoo! One gold star!

Part 2

A fun twist to test run time

The instructions would have me believe:

For each number in list 1
  For each number in list 2
    If there's a match
      Increment a tally by 1

That means list 2 will be checked list 2 length times list 1 length...times.

1000 items in each: 1 million checks

That's not bad. But that seems unnecessary.

All I care about are the counts of each number in list 2.

So, I can check all 1000 numbers once, and build up a map of numbers to their counts. Then, check that list 1000 times.

2000 < 1 million

I like this approach better. To the code!

Building the map of numbers and counts

The example list looks like:

4, 3, 5, 3, 9, 3

So I want an object that looks like:

{
  4: 1,
  3: 3,
  5: 1,
  9: 1
}

With my list2 from my Part 1 algorithm, I need to perform a reduce to build this object:

let counts = list2.reduce((obj, num) => {
  if (!(num in obj)) {
    obj[num] = 1
  } else {
    obj[num] += 1
  }
  return obj
}, {})

To my surprise, that snippet works exactly as expected!

I thought I forgot the correct syntax for num in obj, but that's it!

One simple look-up for each list item

Another reduce with a condition checking for the existence and value associated with a number:

Parse the input into two equal lists of numbers
Sort each list in ascending order
Compare both values at each index
Determine the absolute value after calculating the difference
Increment a tally by the absolute value

Debugging forever because, well, I can't believe it

I kept seeing the wrong score.

I kept wondering why.

I kept adding console.log() statements with more and more values to print.

I kept seeing values that I didn't expect.

Then, I saw it.

I was comparing to list2 and not my custom counts object!

Huge punch to the ego. But just what I needed on Day 1.

Here's the working code:

input.split('\n').split(' ').map(Number)

That generates the correct answer for the example input.

Let's hope it does the same for my puzzle input.

And hopefully it runs lightning fast!

It does!

Yeeeehawwww!!!

Two gold stars to kick things off.

Along with a few beginner mistakes that keep me grounded.

It's all why I love these puzzles.

Onward too Day 2!

The above is the detailed content of Historian Hysteria. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn