Categories
Tech

Advent of Code 2020 days 10 & 11

Day 10

Todays challenge required analysing a list of numbers (output units). The first thing was to place these numbers in an array, sort it, and add 0 (initial output unit) at the begining of the array. I couldn’t find a nice way to regex this one, most likely because the challenge did not involve text processing. Given the list was sorted from the previous steps, and I trust the data to not be poisoned with impossible elements, I used a simple foreach loop to check wether the increase in (output units) is of 1 or 3.

Possibly the fastest solution this year

Part 2 was a bit more of a roller coaster. My initial thoughts involved combinations and permutations. Permutations and combinations are nice and all, but figuring out the adequate mechanisms was beyond my pay grade. I initially wanted to try arriving at the end and work my way from the start, but this doesn’t work as the only fixed point is the start with 0 (output units). By using a hash with the output of the devices as the key and 0 as the initial value, it is possible to traverse the keys in order such that the value is how many routes there are up to that output. The initial output, 0, has only 1 route and is therefore defined before the loop.

Simple iteration

By checking at each key if the next 3 integers are keys, no routes are forgotten, and no need to look at possible combinations of selected or non selected devices which still provide a valid route. The twist at part 2 made it a rather challenging day, while keeping the initial part accessible for people switching languages, brushing up on them, or simply starting out in code.

Day 11

It looks like day 11 is the day my over engineering ways start making sense. Until they don’t. Had to call it a day after spending far too long on part 1. This challenge was fairly interesting, in essence an implementation of the game of life. I started off by selecting the data structure. Against my better judgement, or perhaps due to the better judgement I went with an array of arrays. Or… array of array refs.

Processing input data

Here I already have 2 variables which will help later on for the data processing. After some testing, they are in scope of the subroutine and don’t need to be passed as arguments (trivial to do for the testing if that were the case). The next part was writing the test subroutine. I wanted the subroutine to perform the change on the waiting room and return if it had made a change. At just over 100 lines, this is the engine for this problem.

Some basic definitions
All the edge cases

Each position in the map can have 1 of 3 states: Empty chair, Occupied chair or floor. Floor is never occupied so doesn’t change. Because the mutations all happen simultaneously, I need to check if the adjacent chairs are occupied. However, given some chairs may change states and affect this decision I needed the 2 additional states: Future Empty (FE) and Future Used (FU). By using return 0 I was able ti limit the number of checks done on each chair although that is not necessarily the most elegant solution.

There are only edge cases

Same logic as before, except in this case rather than returning 0, counter went up and was analysed at the end. Of course, if the state is neither empty or occupied, then the floor is lava.

The actual calculation

After a few too many infinite loops (see the interesting debugging tool from the 00’s) this do-while loop provided the solution. I had initially tried $changes++ if testchange($i,$j); but most likely that wasn’t working due to other factors leading to the infinite loops. Used a tiny regex, just for the sake of it. That initial loop does the entire control, as it checks each cell if it will change, thus changing the variable for the control. The second for loop simply standardises the content being worked on.

Finally, the solution to the task at hand:

8/174 lines, or approx 6%

Because this happens after the do-while block the state of the waiting room won’t change. From there it’s a simple nested loop to check the number of occupied chairs. could have been added to the do while loop with a control block depending on changes being equal to 0. I did not have the patience for part 2… maybe later

Categories
code perl Tech

Advent of Code 2020 days 8 & 9

Day 8

For part 1 we’re given a list of instructions, one per line, with 3 possible actions taken. Either we alter a value and move on to the next instruction, we move to a different instruction, or skip and move on to the next line. Not too bad, I can set up a $skip variable, such that when jumping forward the instructions aren’t read and then simply print out the value of the accessor once processing the filehandle is finished. Except the jump instruction also takes negative values => trying to readlines from before sounds like a headache for future Juan. Today I just want a solution, not necessarily an efficient one. The first idea is to get this into a hash of hashes such that as each line is read, an index key is paired with another hash containing 3 key-pair values: {'action':$act, ' 'val': $value, 'exec':0}

Now once the data is nicely in the hash of hashes, it needs to be processed. The first thing is to establish the break point to avoid the infinite loop.

if ($instructions{$index}{exec} == 1){
    print ($acc, "\n");
    die; #exit the loop
} 

Next up was running actually doing the tests which meant testing all keys in order was out of the question. The first index seemes to always be 1, so doing it with a while loop means propper control can be implemented:

$max = keys %instructions;
$id = 1;
while ($id < $max){
    # infinite loop control from before
    #
    # check if the actions are jump or acc 
    # and do something
    # else $id++
}

Most likely it was an error with execution, but this was dying 1 instruction too early. Refactored everything so now data was in an array of arrays.

Solution for Part 1

Part 1 worked fine with no issues. Giving the answer incredibly fast. Part 2 on the other hand, required testing possible mutations of the base instructions. Clearly this means I need to test the array once the instructions are processed. Convert the solution for part 1 into a subroutine as above, and then add a test to verify if no single instruction was used more than once.

testing the arrays

From there it was just a matter of controlling the mutations. Or so I thought.

Part 2

Need to ensure an immutable copy of the instructions is kept [X]
Check if the given instruction causes problems [X]
Test the new array [X]
Find the result [ ]
Debugging shows the control works most of the time. However at a certain point, instead of returning $acc the code seems to enter an infinite loop. Something to check in the future.

Day 9

Todays challenge involved testing a data stream for errors. Each line contains a number and following an introduction buffer, each new number has to be the sum of 2 numbers from the previous buffer. My initial thoughts were to hard code the buffer, but that was misreading the question. Once the buffer for the checks is in place, each new item gets added to the list, and the oldest gets discarded. Fairly simple, can be done while processing the input data: check that the first 25 get read in, then start processing.

Processing for part 1 consisted of checking in a nested loop for each item. To avoid doing 252 checks, the moment a solution was found (multiple solutions possible) it would break the loop. Following the data processing, if no solution had been found, it would print the number and die as I no longer needed to process additional data.

For part 2, it was important to find a continuous list of numbers within the entire datastream such that together they added to the flag in part 1. I didn’t want to change the code from part 1 as it may come in handy later on in the advent, so new array @nums2 holds every item from the list.

Now I want to check every possible set of continuous numbers, without leaving the machine running until the 25th. The question implies there are 2 numbers, which means the largest starting index is 2 less than the size of @nums2. (-1 as array counting starts at 0, -1 as the last array holds $nums[-2] and $nums[-1]). That’s the initial for statement sorted. There are 2 critical breaking points:

  • The starting number in the list is greater than the key from part 1
  • The sum is greater than the key found in part 1.

Solved part one by using the next if, and the second with the while ($sum < $part1) control. For some reason I created the @inc array (for included numbers) and forgot about it while trying to finish part 2. Attempted splicing the @nums2 array but somehow kept getting the wrong highest number. Most likely an indexing issue with the splice function. Used the @inc array and suddenly it worked.

As I look at this now, I realise the foreach (@inc) could have been replaced with

sort @inc;
my ($min, $max) = ($inc[0], $inc[-1]);
# or accessed those values directly

Hindsight is, as always, 20/20.