Corruption Checksum — Python — #adventofcode Day 2

Series: Advent of Code 2017

Today’s challenge is to calculate a rather contrived “checksum” over a grid of numbers.

→ Full code on GitHub

!!! commentary Today I went back to plain Python, and I didn’t do formal tests because only one test case was given for each part of the problem. I just got stuck in.

I did write part 2 out in as nested `for` loops as an intermediate step to working out the generator expression. I think that expanded version may have been more readable.

Having got that far, I couldn't then work out how to finally eliminate the need for an auxiliary function entirely without either sorting the same elements multiple times or sorting each row as it's read.

First we read in the input, split it and convert it to numbers. fileinput.input() returns an iterator over the lines in all the files passed as command-line arguments, or over standard input if no files are given.

from fileinput import input
sheet = [[int(x) for x in l.split()] for l in input()]

Part 1 of the challenge calls for finding the difference between the largest and smallest number in each row, and then summing those differences:

print(sum(max(x) - min(x) for x in sheet))

Part 2 is a bit more involved: for each row we have to find the unique pair of elements that divide into each other without remainder, then sum the result of those divisions. We can make it a little easier by sorting each row; then we can take each number in turn and compare it only with the numbers after it (which are guaranteed to be larger). Doing this ensures we only make each comparison once.

def rowsum_div(row):
    row = sorted(row)
    return sum(y // x for i, x in enumerate(row) for y in row[i+1:] if y % x == 0)

print(sum(map(rowsum_div, sheet)))

We can make this code shorter (if not easier to read) by sorting each row as it’s read:

sheet = [sorted(int(x) for x in l.split()) for l in input()]

Then we can just use the first and last elements in each row for part 1, as we know those are the smallest and largest respectively in the sorted row:

print(sum(x[-1] - x[0] for x in sheet))

Part 2 then becomes a sum over a single generator expression:

print(sum(y // x for row in sheet
          for i, x in enumerate(row)
          for y in row[i+1:]
          if y % x == 0))

Very satisfying!


Webmentions

You can respond to this post, "Corruption Checksum — Python — #adventofcode Day 2", by: liking, boosting or replying to a tweet or toot that mentions it; or sending a webmention from your own site to https://erambler.co.uk/blog/day-02/

Comments & reactions haven't loaded yet. You might have JavaScript disabled but that's cool 😎.

Comments

Powered by Cactus Comments 🌵