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)
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)
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)
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.