Sonar Sweep
Part 1
Simplified problem statement:
- Given a sequence of integers, count how many times there’s an increase in value between two adjacent numbers.
Basically count the number of times a[i+1] > a[i]
.
Basic idea is to just iterate over pairs (the adjacent value) and filter or
count the ones that satisfy the requirement. I’ll resist the usual temptation of
trivializing everything with numpy
tricks.
Pairs of values in Python can be given by zip(lst, lst[1:])
because zip()
stops at the shortest of the iterators. One could also use tee()
or similar to
avoid making a list copy.
For the filter I prefer a comprehension like sum(x < y for x,y in pairs)
or
sum(1 for x,y in pairs if x < y)
. A more militantly functional way to apply
the operator across the pairs could be be starmap(op.lt, pairs)
.
aoc = __import__('aoc-common').aoc()
depths = [int(x) for x in aoc.input_text(1).split()]
increases = lambda lst: sum([x < y for x,y in zip(lst, lst[1:])])
aoc.print_answer(1, 1, increases(depths))
Part 2
- Given a sequence of integers
a[i]
, consider the transformed sequenceb[i] = a[i]+a[i+1]+a[i+2]
(sum of every three contiguous elements), and count the increases of this new sequence as in Part 1.
A generalized solution that would be purely O(n)
no matter what the length
of the sums are, would be something like this:
from collections import deque
def contiguous_sums(k, it):
history = deque()
val = 0
for a in it:
val += a
history.append(a)
if len(history) > k:
val -= history.popleft()
if len(history) == k:
yield val
sums_of_L3 = contiguous_sums(3, depths)
But since k=3
is fixed, the O(n*k)
solution works where we just hardcode it works fine, too:
aoc.print_answer(1, 2, increases([x+y+z for x,y,z in zip(depths, depths[1:], depths[2:])]))