Answers Built From Smaller Answers
Writing Each Answer Down Once
Last timeSolving the Same Thing Over and Over
Keep every answer the moment it is computed and return it when asked again, and the tree of calls collapses to one call per distinct question.
The whole repair
The previous lesson ended with a sentence: anything done repeatedly can be
done once and remembered. Here is that sentence as code.
Keep a store, empty at the start. At the very top of the method, before
anything else, look in the store for this question. If it is there, return the
stored answer immediately. Otherwise compute the answer as before, put it in
the store, and return it.
def ways(n, seen={}):
if n <= 1:
return 1
if n in seen:
return seen[n] # the check comes first, before any work
seen[n] = ways(n - 1, seen) + ways(n - 2, seen)
return seen[n]
import sys
sys.setrecursionlimit(100000) # the depth is now the only limit left
print(ways(50)) # 20365011074, instant
print(len(str(ways(10000)))) # 2090 digits, also instantWhy it collapses
The reason this works is worth stating precisely, because the size of the
improvement looks implausible.
Every call either finds its answer in the store and returns at once, which
costs nothing and makes no further calls, or does not, in which case it
computes and stores. The second case can happen only once per distinct
question, since afterwards the answer is in the store. So the number of calls
that actually do any work is exactly the number of distinct questions.
For the staircase, the distinct questions are the values from zero to .
That is of them, each doing one addition. The method that made two
million calls for thirty steps now makes thirty one.
| calls that do work | calls answered from the | time | |
|---|---|---|---|
| thirty steps, before | 2692537 | 0 | 200 |
| thirty steps, after | 31 | 29 | 0 |
| fifty steps, before | 40730022147 | 0 | 345600000 |
| fifty steps, after | 51 | 49 | 0 |
| ten thousand steps, afte | 10001 | 9999 | 20 |
- how many different argument combinations the method can be called with
Counting the questions first
That formula is more useful before writing the method than after, because it
answers the question of whether the repair is going to be enough.
Look at the arguments. If the method takes one number up to , there are
distinct questions. If it takes two numbers, one up to and one up to ,
there are times . If it takes a position in a list and a remaining
budget, it is the length multiplied by the number of budget values.
That count is both the running time and, as the next section discusses, the
memory. So a method whose arguments are a position up to a thousand and a
budget up to a thousand will do a million units of work, which is fine. A
method whose arguments are three positions each up to a thousand will do a
thousand million, which is probably not. And a method whose argument is a set
of visited places among thirty has a thousand million distinct questions too,
which is where this approach stops being the answer.
The lesson stops here
3 more paragraphs to go
You have read the opening. The rest of the argument, the problems that check whether it landed, and the lines worth keeping at the end all come with a plan.
The first lesson of every course in the library reads the whole way through, free, so you can see exactly what the rest of them are.
See the planThe contentsThis is the reading half
Starting the course gives you your own copy of it. Every idea on every page has problems standing under it, marked with a reason rather than a tick, and any sentence you do not believe can be opened and argued with. None of that can happen on a page nobody owns.
The contents