Source: Chronal Calibration
Part 1: Given a list of numbers (positive and negative) calculate the sum.
(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
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
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…