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

Damien Sedgwick - Sep 5 '22 - - Dev Community

It is time for another Advent of Code 2015 walkthrough and today we are looking at day 2, part 1, "I Was Told There Would Be No Math".

Lets start by checking out the problem.

--- Day 2: I Was Told There Would Be No Math ---

The elves are running low on wrapping paper, and so they need
to submit an order for more. They have a list of the dimensions
(length l, width w, and height h) of each present, and only
want to order exactly as much as they need.

Fortunately, every present is a box
(a perfect right rectangular prism), which makes calculating
the required wrapping paper for each gift a little easier:
find the surface area of the box,
which is 2*l*w + 2*w*h + 2*h*l. The elves also need a little
extra paper for each present: the area of the smallest side.

For example:

A present with dimensions 2x3x4 requires 2*6 + 2*12 + 2*8 =
52 square feet of wrapping paper plus 6 square feet of slack,
for a total of 58 square feet.

A present with dimensions 1x1x10 requires 2*1 + 2*10 + 2*10 =
42 square feet of wrapping paper plus 1 square foot of slack,
for a total of 43 square feet.

All numbers in the elves' list are in feet. How many total
square feet of wrapping paper should they order?
Enter fullscreen mode Exit fullscreen mode

And lets take a quick peak at our input (I've shortened it quite a lot due to the length, there are 1000 lines).

3x11x24
13x5x19
1x9x27
24x8x21
6x8x17
19x18x22
10x9x12
12x2x5
...
Enter fullscreen mode Exit fullscreen mode

So that's it for part 1 of this challenge, lets next move on to breaking the problem down into smaller and more manageable chunks.

Firstly, we are going to load the input from input.txt and full disclosure, this little function is going to be used at the start of each solution but I will no longer include it after this article.

func LoadInput(path string) string {
    input, err := os.ReadFile(path)
    if err != nil {
        log.Fatal(err)
    }

    return string(input)
}
Enter fullscreen mode Exit fullscreen mode

Now that we have our input as a string, we need to split it up so that each present is represented in a slice.

The test for doing so will look like this.

func TestMakePresentSlice(t *testing.T) {
    assert.Equal(t, []string{
        "3x11x24",
        "13x5x19",
        "1x9x27",
        "24x8x21",
    }, MakePresentSlice("3x11x24\n13x5x19\n1x9x27\n24x8x21"))
}
Enter fullscreen mode Exit fullscreen mode

Running go test will now produce a failed test which we will need to go ahead and fix.

func MakePresentSlice(str string) []string {
    return strings.Split(str, "\n")
}
Enter fullscreen mode Exit fullscreen mode

With our tests now passing, the next step is to write a test for a function that can calculate the amount of wrapping paper for each element of the slice.

As part of this process, we will also be converting our value from a string to an int.

Our test will look like this.

func TestCalculatePresentArea(t *testing.T) {
    assert.Equal(t, 58, CalculatePresentArea("2x3x4"))
    assert.Equal(t, 43, CalculatePresentArea("1x1x10"))
}
Enter fullscreen mode Exit fullscreen mode

Just a note, when writing test cases, I try to use as many examples as possible from the instructions.

Here is how we are going to calculate the required feet of wrapping paper per present.

func CalculatePresentArea(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[1]*3 + sides[0]*sides[2]*2 + sides[1]*sides[2]*2
}
Enter fullscreen mode Exit fullscreen mode

This works because each present we pass to this function, converts each side from a string value, into an int and then stores all of the sides in a slice.

We then sort the slice in ascending order and this is why the first calculation sides[0]*sides[1]*3 is multiplied by 3, because we want to add the additional wrapping paper required which is the area of the smallest side.

Becuase our tests are passing, we can correctly calculate each element of the slice, the only thing left to do is to iterate over our string slice (which we have wrote the functions for already) and sum all of the results together.

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

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

    fmt.Println(total)
}
Enter fullscreen mode Exit fullscreen mode

For my input, the result is 1588178 which is the correct answer and another small win for TDD.

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