Post: Advent of Code day 2
This commit is contained in:
parent
76d733b6fd
commit
8754f6d6cb
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
title: "Corruption Checksum — Python — #adventofcode Day 2"
|
||||
description: "In which I detect corrupt spreadsheets."
|
||||
slug: day-02
|
||||
date: 2017-12-02T09:15:46+00:00
|
||||
tags:
|
||||
- Technology
|
||||
- Learning
|
||||
- Advent of Code
|
||||
- Python
|
||||
series: aoc2017
|
||||
---
|
||||
|
||||
|
||||
!!! 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.
|
||||
|
||||
```python
|
||||
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:
|
||||
|
||||
```python
|
||||
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.
|
||||
|
||||
```python
|
||||
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:
|
||||
|
||||
```python
|
||||
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:
|
||||
|
||||
```python
|
||||
print(sum(x[-1] - x[0] for x in sheet))
|
||||
```
|
||||
|
||||
Part 2 then becomes a sum over a single generator expression:
|
||||
|
||||
```python
|
||||
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!
|
Loading…
Reference in New Issue