Day 2: I Was Told There Would Be No Math (Part 2)

Damien Sedgwick - Sep 18 '22 - - Dev Community

We are back and today we are going to be solving part 2 of day 2: "I Was Told There Would Be No Math" from Advent of Code 2015.

Lets take a look at the problem.

--- Part 2 ---

The elves are also running low on ribbon. Ribbon is all the
same width, so they only have to worry about the length they
need to order, which they would again like to be exact.

The ribbon required to wrap a present is the shortest
distance around its sides, or the smallest perimeter of any
one face. Each present also requires a bow made out of ribbon
as well; the feet of ribbon required for the perfect bow is
equal to the cubic feet of volume of the present. Don't ask
how they tie the bow, though; they'll never tell.

For example:

A present with dimensions 2x3x4 requires 2+2+3+3 = 10 feet of
ribbon to wrap the present plus 2*3*4 = 24 feet of ribbon for
the bow, for a total of 34 feet.

A present with dimensions 1x1x10 requires 1+1+1+1 = 4 feet of
ribbon to wrap the present plus 1*1*10 = 10 feet of ribbon for
the bow, for a total of 14 feet.

How many total feet of ribbon should they order?
Enter fullscreen mode Exit fullscreen mode

As with day 1, there is a lot of code we can already use here.

To start, we are going to create a new test so that we can calculate the length of ribbon needed for each present.

func TestCalculateRibbonLength(t *testing.T) {
  assert.Equal(t, 34, CalculateRibbonLength("2x3x4"))
  assert.Equal(t, 14, CalculateRibbonLength("1x1x10"))
}
Enter fullscreen mode Exit fullscreen mode

We have used the examples to create our test cases just as before.

Next up, we need to write the code to make the above tests pass.

func CalculateRibbonLength(str string) int {
  s := strings.Split(str, "x")

  var sides []int
  for _, sideString := range s {
    side, _ := strconv.Atoi(sideString)
    sides = append(sides, side)
  }

  sort.Ints(sides)

  return sides[0] + sides[0] + sides[1] + sides[1] + sides[0]*sides[1]*sides[2]
}
Enter fullscreen mode Exit fullscreen mode

Now if we modify our main function from the first part of the challenge so it now does the following.

func main() {
  input := LoadInput("./input.txt")
  presents := MakePresentSlice(input)

  total := 0
  ribbon := 0
  for _, present := range presents {
    total += CalculatePresentArea(present)
    ribbon += CalculateRibbonLength(present)
  }

  fmt.Println(total, "Feet of wrapping paper needed.")
  fmt.Println(ribbon, "Feet of ribbon needed.")
}
Enter fullscreen mode Exit fullscreen mode

When we run the above code, the output for our ribbon length is 3783758 Feet of ribbon needed and entering this answer into Advent of Code, we get a success message for providing the correct answer.

That's the right answer! You are one gold star closer to powering the weather machine.

Next up, rather than looking at Day 3: part 1, we are going to come back to this challenge for some refactoring.

At the moment, we have two different functions that repeat this same block of code.

...
s := strings.Split(str, "x")

var sides []int
for _, sideString := range s {
  side, _ := strconv.Atoi(sideString)
  sides = append(sides, side)
}

sort.Ints(sides)
...
Enter fullscreen mode Exit fullscreen mode

It would be good to extract this out into its own function to make it more reusable.

Luckily, we are using test driven development so this process should be quick and painless.

. . . . . . . . . . . . . . . . . . . . . .