Advent of Code 2024 - Day 1: Historian Hysteria

:: programming, python, puzzle

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from advent import ints, parse, Counter

left, right = zip(*parse(1, ints))

def part1():
    return sum([ abs(l - r) for l, r in zip(sorted(left), sorted(right)) ])

def part2():
    c = Counter(right)
    return sum([ n * c[n] for n in left ])

# ---------------------------------------------------------------------------------------------

assert part1() == 1189304
assert part2() == 24349736

Parsing

The input for Day 1 consists of two columns of integers with each line containing an integer from the left column and one from the right column:

----------------------------------------------------------------------------------------------------
day01.txt ➜ 14000 chars, 1000 lines; first 7 lines:
----------------------------------------------------------------------------------------------------
58789   28882
27059   23721
86784   91527
72958   13217
95228   20832
77437   82573
33685   76537
----------------------------------------------------------------------------------------------------
parse(1) ➜ 1000 entries:
----------------------------------------------------------------------------------------------------
((58789, 28882), (27059, 23721), (86784, 91527), (72958, 13217), (9522 ... , 52806), (83116, 82954))
----------------------------------------------------------------------------------------------------

Above, we see that parse has parsed the input into a tuple of 2-tuples, with each 2-tuple containing an integer from the left and right columns. Now we need to convert the parsed input from:

((left1, right1), (left2, right2), ... , (leftN, rightN))

to:

(left1, left2, ... , leftN)
(right1, right2, ... , rightN)

We accomplish that on line 3 with zip(*((left1, right1), (left2, right2), ... , (leftN, rightN))). This is a Python trick to essentially convert a list of rows into a list of columns. zip returns a tuple of two lists which we unpack into left and right.

Part 1

The algorithm for part one is:

  • Sort the left and right columns
  • Compute the delta between each successive pair of numbers (left1, right1), (left2, right2), etc.
  • Sum all of the deltas

Part 2

The algorithm for part two is:

  • Count the number of occurrences of each integer in the right column
  • For each integer in the left column, multiply the integer by the number of occurrences in the right column
  • Sum all of those products

New Python Concepts

  • assert
  • abs()
  • Counter
  • import
  • sorted()
  • sum()
  • zip()
  • List comprehensions
  • Parallel assignment
  • Unpacking with *

Conclusion

It’s nice to warm up on these early, easy puzzles - much harder ones are sure to come!