Skip to content

Latest commit

 

History

History
165 lines (124 loc) · 12.5 KB

02.md

File metadata and controls

165 lines (124 loc) · 12.5 KB

Day 02

Part 1

Calculate how many square feet of wrapping paper the elves need.

const input = `4x23x21
22x29x19
11x4x11`

const sum = (acc, val) => acc + val
const result = input
  .split('\n')
  .map((present) => {
    const [l, w, h] = present.match(/(\d+)/g).map(Number)
    const sides = [l * w, w * h, h * l]

    const surfaceArea = 2 * sides.reduce(sum)
    const smallestSide = Math.min(...sides)

    return surfaceArea + smallestSide
  })
  .reduce(sum)

console.log(result)

Try it out on flems.io

Here I got to utilize my Advanced Math Knowledge™ that
2*l*w + 2*w*h + 2*h*l
is the same as
2*(l*w + w*h + h*l)

Part 2

Now the elves need ribbon.

const sum = (acc, val) => acc + val
const result = input
  .split('\n')
  .map((present) => {
    const [l, w, h] = present.match(/(\d+)/g).map(Number)

    const ribbonForWrapping = Math.min(2 * (l + w), 2 * (w + h), 2 * (h + l))
    const ribbonForBow = l * w * h

    return ribbonForWrapping + ribbonForBow
  })
  .reduce(sum)

Quite similar to Part 1; just some different calculations.

Because the sum reducer is needed only once, we can nicely combine the map() and reduce():

const result = input.split('\n').reduce((total, present) => {
  const [l, w, h] = present.match(/(\d+)/g).map(Number)

  const ribbonForWrapping = Math.min(2 * (l + w), 2 * (w + h), 2 * (h + l))
  const ribbonForBow = l * w * h

  return total + ribbonForWrapping + ribbonForBow
}, 0)

console.log(result)

flems

What did I learn?

I learned, once again, that one must be very careful with JavaScript's loose typing.

I initially parsed l, w and h from present like this:

const [, l, w, h] = present.match(/(\d+)x(\d+)x(\d+)/)

When doing Part 2, I was scratching my head why this worked (i.e. provided the correct result):

const ribbonForWrapping = Math.min(
  2 * l + 2 * w,
  2 * w + 2 * h,
  2 * h + 2 * l
)

But this didn't:

const ribbonForWrapping = Math.min(
  2 * (l + w),
  2 * (w + h),
  2 * (h + l)
)

In math, 2*a + 2*b is the same as 2*(a + b). So what's the matter?

The matter was that l, w and h were strings, not numbers. Multiplying numeric strings produces a number, but summing them produces a string:

const a = '3'
const b = '4'

     a  *  b
=== '3' * '4'
=== 12

     a  +  b
=== '3' + '4'
=== '34'

// So this is correct:
    2 *  a  + 2 *  b
=== 2 * '3' + 2 * '4'
=== 6       + 8
=== 14

// But this isn't:
    2 * ( a  +  b )
=== 2 * ('3' + '4')
=== 2 * ('34')
=== 68

Makes sense (sort of), but is annoying and confusing.

So that's why I changed how I parse l, w and h from present:

// Before
const [, l, w, h] = present.match(/(\d+)x(\d+)x(\d+)/)

// After
const [l, w, h] = present.match(/(\d+)/g).map(Number)

As a bonus, the code is cleaner: the regex is shorter and the leading comma is not needed in the destructuring statement.