Advent of Code (Day 2, Part 2)

Advent of Code (Day 2, Part 2)

Welcome to part 2 of day 2 of AoC 2023.

This post is a continuation of my previous post on AoC day 2 part 1. Link to that article can be found at the bottom of the post.

I will skip over some portions of this solution as some of it has already been covered in part 1.

Let's begin.

The Puzzle (Part 2)

Above is a screenshot of the puzzle input for part 2. The puzzle input is the same as part 1.

In part 2, the task is to find the minimum number of red, green, and blue cubes that allow the game record to be possible. The minimum number of each color will simply be the highest quantity of the respective colors.

Using the 3 minimum numbers, the "power" of the game can be found by multiplying these numbers together.

The powers of all the games must then be summed and the sum will be the final answer.

To implement this solution, I simply modified the check() function used in part 1.

Code Walkthrough

def check(lines):
    number_counter = 0
    color_counter = 1

    red_quantities = [ ]
    green_quantities= [ ]
    blue_quantities = [ ]

    lines= lines.split()
    del lines[0:2]

    pairs = len(lines) / 2
    for i in range(int(pairs)):

        red = 0
        green = 0
        blue = 0        

        number = lines[number_counter]
        color = lines[color_counter].replace(",", " ")
        color = color.replace(";", " ")
        color = color.strip()

        if color == "red": 
            red = int(number)
            red_quantities.append(red)

        elif color == "green":
            green = int(number)
            green_quantities.append(green)

        elif color == "blue":
            blue = int(number)
            blue_quantities.append(blue)

        number_counter = number_counter + 2
        color_counter = color_counter + 2

    red_quantities.sort()
    red_min = red_quantities[-1]    #last element of sorted list

    green_quantities.sort()
    green_min = green_quantities[-1]

    blue_quantities.sort()
    blue_min = blue_quantities[-1]    

    total = int(red_min) * int(green_min) * int(blue_min)

    return total


inputfile = open("input.txt", "r")    #open input file in read mode
rawinput = inputfile.read()

mainlst = rawinput.split("\n")    #split elements of the text file wherever there is a space
inputfile.close()

mainlst_index = 0
running_sum = [ ]

for i in range(len(mainlst)):
    x = 0

    x = check(mainlst[mainlst_index]) 
    running_sum.append(x)

    mainlst_index = mainlst_index + 1

answer = sum(running_sum)
print(answer)

Above is the entire solution for part 2. Let's go over the modifications done to the code.

The Main Function

def check(lines):
    number_counter = 0
    color_counter = 1

    red_quantities = [ ]
    green_quantities= [ ]
    blue_quantities = [ ]

    lines= lines.split()
    del lines[0:2]

    pairs = len(lines) / 2
    for i in range(int(pairs)):

        red = 0
        green = 0
        blue = 0        

        number = lines[number_counter]
        color = lines[color_counter].replace(",", " ")
        color = color.replace(";", " ")
        color = color.strip()

        if color == "red": 
            red = int(number)
            red_quantities.append(red)

        elif color == "green":
            green = int(number)
            green_quantities.append(green)

        elif color == "blue":
            blue = int(number)
            blue_quantities.append(blue)

        number_counter = number_counter + 2
        color_counter = color_counter + 2

    red_quantities.sort()
    red_min = red_quantities[-1]    #last element of sorted list

    green_quantities.sort()
    green_min = green_quantities[-1]

    blue_quantities.sort()
    blue_min = blue_quantities[-1]    

    total = int(red_min) * int(green_min) * int(blue_min)

    return total

The first and most obvious modification done to the function is the return value. In the function for part 2, the function no longer returns a "True" or "False". This is not necessary as we are no longer concerned with whether a game is possible or not. Instead, the function will return an integer quantity named "total".

The input argument of the function remains the same as part 1.

At the top of the function, 3 new local variables ("red_quantities", "green_quantities", "blue_quantities") are declared. These are declared as empty lists and are used to store all instances where a quantity of a color appears.

To extract and analyze the color and quantities from the input string, the same "pairs" method is used. The pair is a subset of the input list which contains 2 elements; the first element being the quantity and the second element being the color.

if color == "red": 
            red = int(number)
            red_quantities.append(red)

        elif color == "green":
            green = int(number)
            green_quantities.append(green)

        elif color == "blue":
            blue = int(number)
            blue_quantities.append(blue)

Above is the modified if block for part 2. The if block will now append the quantity of the color to its corresponding color list.

Let's have a look at an example. Game 1 will serve as our input string.

Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green

red_quantities = [4, 1]
green_quantities = [2, 2]
blue_quantities = [3, 6]

Once all the pairs have been iterated through by the for-loop, the function will then sort the 3 color lists using the sort() function. The list will be sorted in ascending order; starting from the smallest quantity.

Since we now have a sorted list, the greatest quantity of a color that appeared in the game can be found by retrieving the last element of the sorted list. To retrieve the last element, the index [-1] is used.

The last element of every list is then stored as "red_min", "green_min", and "blue_min".

To find the power of the game, the 3 aforementioned values are first converted to integers then multiplied with each other. The return of the function call will be the result of this multiplication.

Putting It All Together

inputfile = open("input.txt", "r")    #open input file in read mode
rawinput = inputfile.read()

mainlst = rawinput.split("\n")    #split elements of the text file wherever there is a space
inputfile.close()

mainlst_index = 0
running_sum = [ ]

for i in range(len(mainlst)):
    x = 0

    x = check(mainlst[mainlst_index]) 
    running_sum.append(x)

    mainlst_index = mainlst_index + 1

answer = sum(running_sum)
print(answer)

The main code block has remained relatively the same. Some variables from part 1 have been removed as they are no longer required. An empty list named "running_sum" is declared here.

The for loop has the same functionality as part 1. The difference here is that all the return values of the check() function will be stored in "x". "x" will then be appended to the "running_sum" list.

After the for loop has finished running, the sum() method is used on the "running_sum" list which has now been populated with 100 integers.

The output of the sum() method will be then be printed. This is the final answer.

Conclusion

That's another 2 gold stars !!

Perhaps I will be revisiting Advent of Code 2023 again very soon. It has been a really fun and enriching experience so far to solve these problems. These challenges will also slowly increase in difficulty as the days go by and I'm looking forward to trying more. I may also try tackling other challenges using other languages.

In the meantime though, there are some other projects I need to work on and my progress on AoC 2023 might be put on hold for a little bit. The subject of subsequent blog posts will likely be returning to Arduino programming while I work on developing some other skills in Python.

Thank you for reading !

Link to day 2 part 1: https://ethanh.hashnode.dev/advent-of-code-day-2-part-1