Bart Kessels
Bart Kessels
Passionate open source software engineer who loves to go backpacking

Advent of Code 2022, Day one - Part Two

Advent of Code 2022, Day one - Part Two
This image is generated using Dall-E
  • Prompt: Generate an image of elves around a piece of paper and calculator while trying to calculate the largest number in a minimalistic flat style
  • Preface

    Now that we have the following data structure from our previous post, we start implementing the business logic to retrieve the three highest combined number of calories and add them together.

    1
    2
    3
    4
    5
    6
    7
    
    [
      [ 1000, 2000, 3000 ], // Elve one
      [ 4000 ],             // Elve two
      [ 5000, 6000 ],       // Elve three
      [ 7000, 8000, 9000 ], // Elve four
      [ 10000 ]             // Elve five
    ]
    

    Design

    The objective of the second part of the assignment is to retrieve the three highest amounts of combined calories a single elve is carrying, and them adding those three combined calories together. So we need to sum up all the calories in each list from our data structure and get the three biggest numbers. Once we have those three numbers, we need to add them together for our final result.

    flowchart LR
      subgraph eone["Elve one"]
        direction TB
        ae1["1000"]
        be1["2000"]
        ce1["3000"]
    
        ae1 ~~~ be1
        be1 ~~~ ce1
      end
    
      subgraph eonetotal["Elve one"]
        te1["Total: 5000"]
      end
    
      eone -- "Count calories" --- eonetotal
    
      subgraph etwo["Elve two"]
        ae2["4000"]
      end
    
      subgraph etwototal["Elve two"]
        te2["Total: 4000"]
      end
    
      etwo -- "Count calories" --- etwototal
    
      subgraph ethree["Elve three"]
        direction TB
        ae3["5000"]
        be3["6000"]
    
        ae3 ~~~ be3
      end
    
      subgraph ethreetotal["Elve three"]
        te3["Total: 11000"]
      end
    
      ethree -- "Count calories" --- ethreetotal
    
      subgraph efour["Elve four"]
        direction TB
        ae4["7000"]
        be4["8000"]
        ce4["9000"]
    
        ae4 ~~~ be4
        be4 ~~~ ce4
      end
    
      subgraph efourtotal["Elve four"]
        te4["Total: 24000"]
      end
    
      efour -- "Count calories" --- efourtotal
    
      subgraph efive["Elve five"]
        ae5["10000"]
      end
    
      subgraph efivetotal["Elve five"]
        te5["Total: 10000"]
      end
    
      efive -- "Count calories" --- efivetotal
    
      topThree["TopThree()"]
    
      eonetotal --> topThree
      etwototal --> topThree
      ethreetotal --> topThree
      efourtotal --> topThree
      efivetotal --> topThree
    
      topThreeOne["11000"]
      topThreeTwo["24000"]
      topThreeThree["10000"]
    
      topThree --> topThreeOne
      topThree --> topThreeTwo
      topThree --> topThreeThree
    
      sum["Sum()"]
      biggest["Total: <b>45000</b>"]
    
      topThreeOne --> sum
      topThreeTwo --> sum
      topThreeThree --> sum
    
      sum --> biggest
    

    Implementation

    Business logic

    Now we know what we want our code to do, let’s start implementing it in our PartOne class.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    class PartTwo(
        private val sanitizer: Sanitizer
    ) {
        fun getResult(): Int {
            val data = sanitizer.getItems()
            val totalCalories = data?.map { it.sum() }              // 1
            val sortedCalories = totalCalories?.sortedDescending()  // 2
            val topThreeMostCalories = sortedCalories?.subList(     // 3
                fromIndex = 0,
                toIndex = 3 // toIndex is three instead of two because it's exclusive
            )
            val mostCalories = topThreeMostCalories?.sum()          // 4
    
            return mostCalories ?: -1
        }
    }
    

    What our code does is, it creates a new list based on the input in step 1. This new list will contain the summed up values of the calories for each elve. This data structure looks like this

    1
    2
    3
    4
    5
    6
    7
    
    [
      5000,
      4000,
      11000,
      24000,
      10000
    ]
    

    Next, in step 2 we sort the new list in ascending order. Thus the highest number is placed in the front of the list, and the smallest number at the end of the list. We then retrieve the first 3 items from that list in step 3, as those are the three biggest numbers in the list.

    Then finally we sum up the three numbers in that list, and return that value.

    Test case

    Because we know that the three biggest numbers from the elves are 11000, 24000 and 10000, we can add them up to get a total of 45000 and use that as our expected outcome in the test case.

    So we can write a test case that validates our test input to the outcome of 45000. Right now we can update the PartTwoTest class with the following contents.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    class PartTwoTest {
        @Test
        fun testGetResult() {
            // Arrange
            val resource = {}::class.java.getResource("/input.txt")
            val sanitizer = Sanitizer(resource)
            val sut = PartTwo(sanitizer)
            val expectedCalories = 45000
    
            // Act
            val result = sut.getResult()
    
            // Assert
            assertEquals(expectedCalories, result)
        }
    }
    

    Categories

    Related articles

    Advent of Code 2022, Day one - Sanitizer

    Parse the input for day one into a table of elves.

    Advent of Code 2022, Day one - Part One

    Count the calories that each elve is carrying