Categories
code perl Tech

Advent of Code 2020 day 14

Day 14

The days challenge starts explaining that a binary representation needs to be observed with a filter, and then the new representation stored in a specific place of memory. It is not mentioned at any point that memory is full, suggesting that a hash table will allow for the best way of storing the values. The first roadblock is accessing the elements of the mask, this is made easy by using split and storing the mask as an array.

Storing the mask

There are 2 possibilities. Either the mask is updated, or a value is stored in memory. After chomping the line, we immediately check if it is a mask instruction. If it is a mask instruction, we extract the 36 characters by extracting the match to 36 adjacent characters composed of 1, 0 and X. The extraction is then split into @mask (declared outside of scope because… scope.

The second part didn’t allow for 2 greedy matched. $line =~ /(\d+).*(\d+)/ only matches the first digit of the second pattern. Overcame the issue by using substitutions and matching twice with $1.

Extracting the memory adress and value

As the value is given in decimal, sprintf provides a string representation of the binary. From there it’s split into an array, and 0s added to the front until it is the same size as the mask. Given that the value can have different sizes, using the last index of the array as the control allows to verify the size without calculating the size. Finally, conversion back in decimal is done using the builtin oct function.

Finally, find the sum of the values using a simple foreach loop:

Part 1

The main challenge here was working with decimal and binary representations and changing between them. Additionally, because of the binary numbers are not stored as strings, analysing them on a character by character basis meant converting into an array of chars. Highly similar to a C representation.

Link: https://github.com/jspinel/AdventofCode/tree/main/2020/14

Categories
Tech

Advent of Code 2020 days 12 & 13

Day 12

The first part of this day’s challenge was primarily comprised of vector maths. From the text, it comes that the current position relative to the starting point, and the current bearing need to be controlled.

Keeping the position & bearing

From there the first part was analysing the input data and changing position when NSEW commands appear. Following this was correcting the bearings. The input data only has multiples of 90, which means once the bearings are corrected no function is needed to move in diagonals. By correcting the bearing at the beginning of the routine the move Forward instructions can use the NSEW instructions, with no need to create additional subroutines or otherwise.

Small REGEX

The regex matches all lines of the input due to the given format. It avoids needing to convert between data structures with split / join and provides the ability to include data validation should it be required. The do-if instructions replace Switch cases while maintaining readability (as opposed to continuous if blocks). Finally, the result requires to find the Manhattan Distance, which is the sum of the absolute values of the coordinates.

Day 13

This day input was on 2 rows, where the data did not have the same format. The first row was a timestamp, and the 2nd row had a list of bus numbers. In order to process this, I decided to use an array temporarily, such that I could then access the input data outside of the readline loop.

Odd data formats

@buses2 is for the 2nd part of the day’s challenge. The bus numbers are not provided in increasing order. However, it makes sense to assume that smaller bus numbers will come by more regularly hence sorting the @buses array. Because we are only interested in buses active that day, we can get rid of all the elements containing an x. Following that we look for the first time at which a bus arrives.

Part 1 loop

The loop is fairly simple:
First check if a bus arrives at the given time. If not, increase time by 1. Should a bus arrive, get the bus id and find how long it took to wait for this bus. Since now there is a definite departure, increase $departure in order to exit the while loop.

The second part of the challenge is to find at which time the buses depart at their respective offsets. Given I don’t have the list ordering use of @buses2 comes up. (Could also have read the file into memory again). The naive solution is to check timestamps and then use nested if blocks to see if at the next level a bus arrives. However, the first bus ID is most likely not 1. This means there are N failed tests before hitting the first bus. The same at each subsequent level. This is solved by using a bit of modulo arithmetic: if the first bus is 7, then the next time it arrives will be at time 14, then 21. By moving to those positions directly, negative tests are then only involved with the next bus in the list.

The hash table used a key:value pair system comprised of position:bus id for all buses where the id exists. The above image shows some debugging elements. For each bus we are going to look for the point at which a time stamp hits the next bus in the list. The moment a bus is found at the given time stamp (if condition) exit the while loop and multiply the amount timestamp is incremented by, such that all previous bus conditions remain used. At the final level, the print statement provides the timestamp at which all buses are found.