Advent of Code Day 2

8 minute read Published:

Lessons from a brutal humbling in Day 2

After achieving my goal of getting at least one point by placing in the top 100 finishers at some point on Day 1, I was psyched for Day 2.

In addition, this time I was at home where I got to use a monitor and my Kinesis Advantage keyboard.

Part 1

--- Day 2: Corruption Checksum ---

As you walk through the door, a glowing humanoid shape yells in your direction. "You there! Your state appears to be idle. Come help us repair the corruption in this spreadsheet - if we take another millisecond, we'll have to display an hourglass cursor!"

The spreadsheet consists of rows of apparently-random numbers. To make sure the recovery process is on the right track, they need you to calculate the spreadsheet's checksum. For each row, determine the difference between the largest value and the smallest value; the checksum is the sum of all of these differences.

For example, given the following spreadsheet:

5 1 9 5
7 5 3
2 4 6 8

  - The first row's largest and smallest values are 9 and 1, and their difference is 8.
  - The second row's largest and smallest values are 7 and 3, and their difference is 4.
  - The third row's difference is 6.

In this example, the spreadsheet's checksum would be 8 + 4 + 6 = 18.

What is the checksum for the spreadsheet in your puzzle input?

Attempt

I starting panicking a bit because I realized that I couldn’t have new lines in the INPUT variable so the first solution that came to mind was to replace the new lines with commas by going to the end of the line in vim navigation mode Shift-A, then Delete then , then Escape. After that, I just used the Vim . and down arrow to edit each line. I lost some time here which I could have saved by writing a function to hit the advent of code input url and reading that text file.

I also realize that I lost some time because I had NERDTree open in Vim which forced me to take 3 keystrokes instead of 2 to get to the other pane to run my code.

INPUT="3458    3471    163    1299    170    4200    2425    167    3636    4001    4162    115    2859    130    4075    4269,2777    2712    120    2569    2530    3035    1818    32    491    872    113    92    2526    477    138    1360,2316    35    168    174    1404    1437    2631    1863    1127    640    1745    171    2391    2587    214    193,197    2013    551    1661    121    206    203    174    2289    843    732    2117    360    1193    999    2088,3925    3389    218    1134    220    171    1972    348    3919    3706    494    3577    3320    239    120    2508,239    947    1029    2024    733    242    217    1781    2904    2156    1500    3100    497    2498    3312    211,188    3806    3901    261    235    3733    3747    3721    267    3794    3814    3995    3004    915    4062    3400,918    63    2854    2799    178    176    1037    487    206    157    2212    2539    2816    2501    927    3147,186    194    307    672    208    351    243    180    619    749    590    745    671    707    334    224,1854    3180    1345    3421    478    214    198    194    4942    5564    2469    242    5248    5786    5260    4127,3780    2880    236    330    3227    1252    3540    218    213    458    201    408    3240    249    1968    2066,1188    696    241    57    151    609    199    765    1078    976    1194    177    238    658    860    1228,903    612    188    766    196    900    62    869    892    123    226    57    940    168    165    103,710    3784    83    2087    2582    3941    97    1412    2859    117    3880    411    102    3691    4366    4104,3178    219    253    1297    3661    1552    8248    678    245    7042    260    581    7350    431    8281    8117,837    80    95    281    652    822    1028    1295    101    1140    88    452    85    444    649    1247".split(',')

sum = 0
for line in INPUT:
    most = -100000
    least = 100000
    for val in line.split('   '):
        num = int(val)
        most = max(num, most)
        least = min(num, least)
    sum = sum + most - least

print sum

I also hard coded the most and least variables which I could have easily gotten around by getting the first element in the row. This also ended up costing me debugging time since I started with least too low. I ended up finishing in 6 minutes, 21 seconds with a rank of 450.

Refactoring

This was a good opportunity to clean up my ugly code. I went back and did this the next day. First I tried getting the input automatically using urllib2.urlopen but realized that this required some form of authentication.

After watching someone achieve top 5 on the second part of Day 2 on Youtube, I decided to try a modified version of his default setup. I was sure why he had random imported. (Maybe for simulations?)

from collections import *
import itertools
import sys

def main():
    sum = 0
    for line in sys.stdin:
        a = list(map(int, line.strip().split()))
        sum += max(a) - min(a)
    print sum

main()

Then I ran python 2_1.py 2.in to get my result.

Part 2

--- Part Two ---

"Great work; looks like we're on the right track after all. Here's a star for your effort." However, the program seems a little worried. Can programs be worried?

"Based on what we're seeing, it looks like all the User wanted is some information about the evenly divisible values in the spreadsheet. Unfortunately, none of us are equipped for that kind of calculation - most of us specialize in bitwise operations."

It sounds like the goal is to find the only two numbers in each row where one evenly divides the other - that is, where the result of the division operation is a whole number. They would like you to find those numbers on each line, divide them, and add up each line's result.

For example, given the following spreadsheet:

5 9 2 8
9 4 7 3
3 8 6 5

  - In the first row, the only two numbers that evenly divide are 8 and 2; the result of this division is 4.
  - In the second row, the two numbers are 9 and 3; the result is 3.
  - In the third row, the result is 2.

In this example, the sum of the results would be 4 + 3 + 2 = 9.

What is the sum of each row's result in your puzzle input?

Attempt

At this point I realized I probably wouldn’t make it onto the leaderboard but decided that I might as well try to finish up and see how I do. I reused code and was super lazy about setting variables. Here was my attempt at Part 2. Again I stumbled about trying to debug my code for some time because of how messy it was.

INPUT="3458    3471    163    1299    170    4200    2425    167    3636    4001    4162    115    2859    130    4075    4269,2777    2712    120    2569    2530    3035    1818    32    491    872    113    92    2526    477    138    1360,2316    35    168    174    1404    1437    2631    1863    1127    640    1745    171    2391    2587    214    193,197    2013    551    1661    121    206    203    174    2289    843    732    2117    360    1193    999    2088,3925    3389    218    1134    220    171    1972    348    3919    3706    494    3577    3320    239    120    2508,239    947    1029    2024    733    242    217    1781    2904    2156    1500    3100    497    2498    3312    211,188    3806    3901    261    235    3733    3747    3721    267    3794    3814    3995    3004    915    4062    3400,918    63    2854    2799    178    176    1037    487    206    157    2212    2539    2816    2501    927    3147,186    194    307    672    208    351    243    180    619    749    590    745    671    707    334    224,1854    3180    1345    3421    478    214    198    194    4942    5564    2469    242    5248    5786    5260    4127,3780    2880    236    330    3227    1252    3540    218    213    458    201    408    3240    249    1968    2066,1188    696    241    57    151    609    199    765    1078    976    1194    177    238    658    860    1228,903    612    188    766    196    900    62    869    892    123    226    57    940    168    165    103,710    3784    83    2087    2582    3941    97    1412    2859    117    3880    411    102    3691    4366    4104,3178    219    253    1297    3661    1552    8248    678    245    7042    260    581    7350    431    8281    8117,837    80    95    281    652    822    1028    1295    101    1140    88    452    85    444    649    1247".split(',')

sum = 0
for line in INPUT:
    for i in xrange(0, len(line.split('   '))):
        for j in xrange(i, len(line.split('   '))):
            most = int(line.split('    ')[i])
            least = int(line.split('    ')[j])
            if most > least and most % least == 0:
                sum = sum + most/least
            elif most < least and least % most == 0:
                sum = sum + least/most

print sum

I ended up finishing both parts in 13 minutes and 29 seconds, which resulted in a rank of 393. The cutoff time for the top 100 was 6 minutes and 13 seconds which was less time than it took me to solve part 1.

Refactoring

Here is how I would refactor it. I normally wouldn’t use one letter variable names except maybe for indices. Also xrange() is faster than range() but for these questions, runtime is negligible so from now on I’ll be using range to save a keystroke.


from collections import *
import itertools
import sys

def main():
    sum = 0
    for line in sys.stdin:
        a = list(map(int, line.strip().split()))
        for i in range(len(a)):
            for j in range(len(a)):
                if i != j and a[i] % a[j] == 0:
                    sum += a[i] / a[j]
    print sum

main()

Conclusion

For the next challenge, I’ll be using a template and piping in input instead of copy pasting it into Python. I probably also didn’t need to have multiple tabs open pointing to the input and the question.

Day 2’s Results

You have 37 points.

      -------Part 1--------   -------Part 2--------
Day       Time  Rank  Score       Time  Rank  Score
  2   00:06:21   450      0   00:13:29   393      0
  1   00:03:32    86     15   00:05:32    79     22