The other answer already mentioned to use descriptive names.
It's the most important point to make it easier to understand the code.
It's recommended to add more spaces around operators.
Tools like PyCharm would format the posted code like this:
def s(d, p=0):
if (len(d) > 1):
return s([i[0] - i[1] for i in zip(d[1:], d[:-1])], p + d[-1])
return p + d[-1]
The parentheses in the if
condition are unnecessary, drop them.
Instead of checking if the sequence has a single element,
you can make that condition based on if the sequence is empty,
which would make the code a bit simpler:
def s(d, p=0):
if d:
return s([i[0] - i[1] for i in zip(d[1:], d[:-1])], p + d[-1])
return p
Be careful with recursive logic,
if there are too many items in the input sequence,
the call stack may become too deep and overflow.
Consider writing in iterative style,
especially when it's possible with little effort,
and without sacrificing readability.
Here's an alternative using iterative style (with the nice renames from the other answer):
def predict(seq, prev=0):
while seq:
prev += seq[-1]
seq = [b - a for a, b in zip(seq[:-1], seq[1:])]
return prev
As @AJNeufeld pointed out in a comment,
this can still be significantly better.
The prev
argument is not really meant to be used by callers,
it was necessary in the recursive version to track the cumulative sum of differences,
but in the iterative version it can be a local variable.
It's also important to note that while zip(seq[:-1], seq[1:])
is elegantly written, it incurs the cost of list slicing (array copies).
From Python 3.10, a more efficient and even more elegant solution is to use itertools.pairwise
.
Putting these tips together:
def predict(seq):
prev = 0
while seq:
prev += seq[-1]
seq = [b - a for a, b in itertools.pairwise(seq)]
return prev