Corruption Checksum — Python — #adventofcode Day 2
This post is part of the series Advent of Code 2017
- Reflections on #aoc2017
- The Halting Problem — Python — #adventofcode Day 25
- Electromagnetic Moat — Rust — #adventofcode Day 24
- Coprocessor Conflagration — Haskell — #adventofcode Day 23
- Sporifica Virus — Rust — #adventofcode Day 22
- Fractal Art — Python — #adventofcode Day 21
- Particle Swarm — Python — #adventofcode Day 20
- A Series of Tubes — Rust — #adventofcode Day 19
- Duet — Haskell — #adventofcode Day 18
- Spinlock — Rust/Python — #adventofcode Day 17
- Permutation Promenade — Julia — #adventofcode Day 16
- Dueling Generators — Rust — #adventofcode Day 15
- Disk Defragmentation — Haskell — #adventofcode Day 14
- Packet Scanners — Haskell — #adventofcode Day 13
- Digital Plumber — Python — #adventofcode Day 12
- Hex Ed — Python — #adventofcode Day 11
- Knot Hash — Haskell — #adventofcode Day 10
- Stream Processing — Haskell — #adventofcode Day 9
- I Heard You Like Registers — Python — #adventofcode Day 8
- Recursive Circus — Ruby — #adventofcode Day 7
- Memory Reallocation — Python — #adventofcode Day 6
- A Maze of Twisty Trampolines — C++ — #adventofcode Day 5
- High Entropy Passphrases — Python — #adventofcode Day 4
- Spiral Memory — Go — #adventofcode Day 3
- > Corruption Checksum — Python — #adventofcode Day 2 <
- Inverse Captcha — Coconut — #adventofcode Day 1
- Advent of Code 2017: introduction
Today’s challenge is to calculate a rather contrived “checksum” over a grid of numbers.
!!! 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 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))