AoC-2021

Repository for my solutions to Advent of Code 2021.

Python Solutions

I calculated the overall execution time from each part 1 and part 2 solutions (given my own inputs) alongside my time completion of puzzles (from 5am UTC start time) and my global rank for them:

Day Part 1 Time Part 2 Time (Accumulated) Overall Execution Time (s) Global Rank
Day 1 00:13:37 00:27:13 0.002 5960
Day 2 00:16:35 00:19:02 0.002 7843
Day 3 00:28:22 00:42:05 0.001 4294
Day 4 01:05:35 01:19:33 0.050 5906
Day 5 00:25:35 00:38:44 0.130 2995
Day 6 00:15:52 00:24:23 0.503 2685
Day 7 00:10:59 00:19:08 0.400 4856
Day 8 00:53:401 01:35:09 0.005 4498
Day 9 00:37:06 01:37:18 0.005 7399
Day 10 00:26:18 00:58:55 0.003 7274
Day 11 02:55:922 03:09:17 0.040 10232
Day 12 08:14:183 08:56:02 0.450 17522
Day 13 00:39:36 00:41:504 0.004 3420
Day 14 07:22:065 >24h 0.011 36937
Day 15 03:43:19 03:51:19 5.765 6729
Day 16 10:01:36 10:07:11 0.004 10935
Day 17 09:58:11 11:39:48 0.077 15199
Day 18 >24h6 >24h 0.832 16901
Day 19 >24h >24h 7.504 12519
Day 20 04:24:447 04:25:51 4.000 5884
Day 21 09:08:19 >24h 0.434 14314
Day 22 05:29:29 06:59:41 14.98 3755
Day 23 05:56:128 07:35:40 6.388 2754
Day 24 13:23:02 13:25:57 0.001 4263
Day 25 00:59:08 00:59:29 4.584 1836

Blueprint Solutions

My goal with these blueprint solutions is that I want to try and match them to the Python solutions I write first. If I find a better way of doing things, I update it in the Python solution first, and then update the blueprint solution. This is partially because I find it difficult to write BP if I don't have code to follow along with. Building upon this, it makes debugging the BP solution much easier since I can debug the Python solution as a reference. The only times this does not hold directly true is when I use a datastructure or library that does not exist in BP and I have to recreate with something my own, for example a defaultdict or Counter from collections.

Reading in the input

BP cannot do file I/O on its own so I had to write a couple of small C++ functions to read in the input. Read Input C++
I then have a Blueprint Library with a function helper functions, including Read Input that calls upon the reflected C++ functions. I also have a pre-path set to the input text files directory so that in each new Day BP I only need to change the file name. Read Input BaseLib I then have a Base BP Actor that has a couple of variables and nodes already set up. I then can just duplicate the Base BP Actor and build my solutions from there. Base BP Actor

Day 1

Day 1

Day 2

Day 2

Day 3

There were a few different functions for various processes so I took screenshots of the most important ones. The first screenshot is the main function for parts 1 and 2. I wrote the BP code based off my Python solution. Day 3 Main This function below counts the number of 1s and 0s in each column and stores them into a struct. Day 3 Create Counter This converts the binary string to a decimal number, since UE does not have a built in function for this. Day 3 Binary To Decimal The below function is effectively the main function for part 2, but since it gets called twice for the oxygen and C02 scrubbers I had to make it a separate function. Day 3 Get Rating This function filters out the lines to determine the sole rating. Day 3 Filter Lines

Day 4

Day 4's input is so complex that I just did not want to spend the time to write a solution in BP.

Day 5

Since parts 1 and 2 were very similar, I was able to put them into the same function with a parameter that checked which part was being run.
Day 5 Main
The overall program loop. Day 5 Find Vents This parses the input into the array of structs where element 0 and 1 are integer arrays. This was basically my lists data structure you can see in my Python solution. Day 5 Parse Input This function sets the x1, x2, y1, y2 values for part 1 plus the dx and dy values for part 2. Day 5 Set Coords Then it does all checks for line intersections... Day 5 Create Grid ...and passes them into this function which adds them to a grid - which here is a struct where element 0 is an integer array (stores x, y coordinates) and element 0 is the count of intersections on each coordinate. Day 5 Add Line To Grid It also has to do an additional check to see if the coordinate already exists in the grid, which then increments the count at that coordinate. Day 5 If Coords Exist

Day 6

Since parts 1 and 2 were very similar, I was able to put them into the same function with a parameter that checked which part was being run.
Day 6 Main
First I needed to parse the input into an array. This was actually more difficult than I thought it would be, for whatever reason. Day 6 Parse Input The overall program loop that counts the fish. As you can see, I had to use int64 for the count because I was getting reaching the bit limit. Sometimes doing so much programming in BP breaks my brain and so it took me a solid 10 minutes to figure out how to convert from int64 to string, since UE4 does not have a built in cast for this, and obviously I cannot just convert to int to string as it would hit the bit limit again. Day 6 Count Fish This function takes the starting ages and returns the list of fish at the start. Day 6 Add Fish

Day7

Day 7 Main At first I thought I could just nick my parse input function from day 6, however I built it assuming that the numbers were all 1 digit, and since day 7 input as numbers of more than 1 digit, I could not use it. I know that I could modify it by 1) checking for the number of characters before the delimeter since last being split 2) add those chars to a string 3) converting to an int 4) adding to the int array. However, I couldn't really be bothered and decided to cheat a little by writng a C++ function to do it for me. Day 7 Parse Input For my solution to work, I needed to sort the array. However, BP does not have a built in sort function, so I had to write my own. I decided to use insertion sort because although it's not the most efficient (O(n^2)), it's the easiest to write - I tried writing quick sort first but my implementation did not work and I couldn't figure out why. Day 7 Sort I then just wrote the functions that I have in my Python solution. Day 7 Middle Day 7 Fuel Usage Day 7 Fuel Cost Basically my part 2 solution. Day 7 Variable Fuel Usage

Day 8

I only managed to do Part 1 because I was unable to figure out how to do Part 2. Day 8 Main Day 8 Parse Input Day 8 Count Digits Before I discovered the Parse Into Array function that you can see in the above image, I tried writing my own first. I successfully wrote the function... but it used recursion, which although UE allows, I do NOT recommend. UE completely dies, as the initial function call has the first element become a call by reference, which although seems fine at first, it is not. Whilst debugging, the array passed by reference claims to have a value, but when I pass the array into a function, there is no value. So the function does not actually do anything. I asked a lot of UE4 developers and no one knew, but someone finally pointed me towards this Parse Into Array function that already exists, thankfully. So from now on I have know I am unable to implement recursive functions. Day 8 Recursive Mess

Day 9

Day 9 was a bit of a copout, although slightly less so than Day 8. Part 1 was so easy that I programmed it all and it worked first time! But part 2, which involves recursion with depth first search, did not go so well. I tried giving it a second shot but got the same issue as in Day 8. So I decided to write part 2 in C++. Day 9 Main I had to parse the input lines into the grid first. Since 2D arrays do not exist, this had to be an array of structs of an array of ints. Day 9 Make Grid Then it was just a bunch of if statements to check for the risk level of the grid. Day 9 Get Risk For part 2 I basically just wrote a C++ version of my Python solution. Day 9 Map Basins Day 9 DFS

Day 10

I kid you not, I was able to complete both parts first try (i.e. making them and working as intended instantly). Felt so good! Day 10 Main Part 1. Day 10 Part 1 Part 2. Day 10 Part 2 I had to write an Int64 version of my insertion sort function from Day 7. Day 10 Sort

Day 11

This was really hard to debug! At one point I was getting an error that wouldn't crash the program, but rather put it into limbo - the program was trying to access some really high index numbers for an array of size 3. Turns out I wasn't creating the original grid correctly. Day 11 Main I'll show each step function first, then the two parts, as they use the same step functions. Step 1. Day 11 Step 1 Step 2. Day 11 Step 2 Step 3. Day 11 Step 3 Getting the adjacent tiles. Day 11 Get Adjacent Tiles Part 1. Day 11 Part 1 Part 2. Day 11 Part 2

I haven't given up (edit - ok maybe I have)... just no time to work on these solutions as they are very complex :)

Footnotes

  1. I woke up 35 minutes late.

  2. I woke up 2 hours 10 minutes late.

  3. I woke up 7 hours 30 minutes late. It was worth it though. It was the best night's sleep I've had since the 31st of November!

  4. I actually could tell what part 2 was going to be, so I predicted it before I submitted my part 1 solution, so that I could try and get like a 2 second delta. But like an absolute idiot I got the solution in the debugger output so when I needed it I was panicking because I couldn't find it and I had messed about in the code for a bit in between. So my delta ended up being just over 2 minutes... 🤦‍♂️

  5. I woke up with a cold, which then lasted all the way up until Day 20. So I was prioritising sleep over this :)

  6. I "cheated" a little bit today by allowing myself to use permutations and reduce from itertools and functools respectively, but I'm still happy about it - I did this on Day 20!

  7. Yay finally! The first day since getting a cold that I could stay awake for long enough (I woke up at 8am) without my eyes watering or coughing my lungs out! Still kinda sick though, so I'm going straight back to sleep. Hopefully I'll feel even better tomorrow.

  8. I solved part 1 and 2 by hand first, then went on to write an actual solution for part 2 because, well, I was interested in how the problem should actually be solved. I should note that I did ask for tips on where to look for the coded solution first - because I honestly had no idea.