This recipe allows for individual number generation, and allows for generations of number ranges as well.
The recipe automatically memorizes numbers generated before and keeps them through out the running of the script. This recipe cannot handle too large of numbers, but does act as a simple solution for most cases.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #/usr/bin/python
# fib.py
"""
Number generator
Uses cPickle to save and load previously calculated numbers. Could be improved to use databases or
other mathods which are faster.
"""
import os
from cPickle import dump, load, HIGHEST_PROTOCOL
class LoadableDict(dict):
def __init__(self, filename="loadeddict.dict", *args, **kw):
dict.__init__(self, *args, **kw)
self.filename = filename
self.load()
def load(self, filename=None):
filename = filename or self.filename
if not os.path.exists(filename):
return
with open(filename, "rb") as f:
d = load(f)
assert isinstance(d, dict)
self.loaddict(d)
def loaddict(self, d):
for key, value in d.iteritems():
self[key] = value
def save(self, filename=None):
filename = filename or self.filename
with open(filename, "wb") as f:
dump(self, f, HIGHEST_PROTOCOL)
def __del__(self):
self.save()
try:
_mem = LoadableDict("fib.dict", {1: 0, 2: 1})
except MemoryError:
os.remove("fib.dict")
_mem = LoadableDict("fib.dict", {1: 0, 2: 1})
def fib(n):
if n in _mem:
return _mem[n]
for i in xrange(1, n+1):
if i in _mem:
continue
else:
_mem[i] = _mem[i-1] + _mem[i-2]
return _mem[n]
def fibrange(start, stop=None, step=1):
if stop is None:
stop, start = start, 0
return (fib(n+1) for n in xrange(start, stop, step))
|