AoC 2018 Day 1: Sum-thing to start with

Source: Chronal Calibration

Part 1: Given a list of numbers (positive and negative) calculate the sum.

First, in Racket. We have to take all the numbers in a file (which are read able, so you can do that with port->list , which reads an entire port into a list. Then just apply + to the whole shebang1:

(apply + (port->list))

That really does work:

$ cat input.txt | racket summification.rkt

416

It’s a bit more verbose in Python, but only barely:

sum = 0
for line in fileinput.input():
    sum += int(line.strip())

print(sum)

And this way we get to leverage the lovely fileinput library, which means we can run it a couple different ways:

$ cat input.txt | python3 summification.py

416

$ python3 summification.py input.txt

416

Part 2: Assuming the same input loops forever, what is the first running sum that you see twice?

Since we aren’t just reading the entire input once (it could be less than once if we see a duplicate quickly or many times, depending on the input2), this isn’t quite as easy to write up.

In Racket, what we want to do is first capture the input list, then set up a loop that will keep track of three things:

  • The current input (which will reset when we run out)
  • The current sum
  • All sums we’ve seen before so we can detect duplicates

We can do all that with this:

(define input (port->list))

(let loop ([seq input]
           [sum 0]
           [seen (set)])
  (cond
    [(null? seq)
     (loop input sum seen)]
    [(set-member? seen (+ (first seq) sum))
     (+ (first seq) sum)]
    [else
     (define new-sum (+ (first seq) sum))
     (loop (rest seq) new-sum (set-add seen new-sum))]))

None too shabby.

In this case, the Python code can lean on a library that the Racket code cannot (as easily), using the itertools library (specifically the cycle function) to automagically make a cycle of the input without us having to do anything3!

sum = 0
seen = set()

for line in itertools.cycle(fileinput.input()):
    sum += int(line.strip())
    if sum in seen:
        break
    seen.add(sum)

print(sum)

And–as hoped–we get the same input in both cases:

$ cat input.txt | racket duplification-detector.rkt

56752

$ cat input.txt | python3 duplification-detector.py

56752

1 done! 24 to go…


  1. It’s funny because shebang (unix)↩︎

  2. It’s not actually guaranteed to even terminate. Consider the input that is just the number 1. ↩︎

  3. Racket does have in-cycle , but I didn’t quite get it to work cleanly with what we want here. ↩︎