Data update

This commit is contained in:
Ingy döt Net 2025-02-27 18:35:13 -05:00
parent 8e4e15fa56
commit 72eb4943cb
1853 changed files with 35514 additions and 9441 deletions

View file

@ -1,19 +1,19 @@
from itertools import islice, cycle
def fiblike(tail):
for x in tail:
yield x
for i in cycle(xrange(len(tail))):
def fiblike(init_values=(0, 1)):
tail = list(init_values)
yield from tail
for i in cycle(range(len(tail))):
tail[i] = x = sum(tail)
yield x
fibo = fiblike([1, 1])
print list(islice(fibo, 10))
print([*islice(fiblike(), 10)])
lucas = fiblike([2, 1])
print list(islice(lucas, 10))
print([*islice(lucas, 10)])
suffixes = "fibo tribo tetra penta hexa hepta octo nona deca"
for n, name in zip(xrange(2, 11), suffixes.split()):
fib = fiblike([1] + [2 ** i for i in xrange(n - 1)])
suffixes = dict(enumerate('fibo tribo tetra penta hexa hepta octo nona deca'.split(), start=2))
for name, n in suffixes.items():
fib = fiblike([1] + [2 ** i for i in range(n-1)])
items = list(islice(fib, 15))
print "n=%2i, %5snacci -> %s ..." % (n, name, items)
print(f'n={n:>2}, {name:>5}nacci -> {items} ...')

View file

@ -0,0 +1,34 @@
from itertools import chain
def A000032():
'''Non finite sequence of Lucas numbers.
'''
return unfoldr(recurrence, [0, 1])
def n_step_fibonacci(n):
'''Non-finite series of N-step Fibonacci numbers,
defined by a recurrence relation.
'''
return unfoldr(
recurrence,
chain(
(0,),
(2 ** i for i in range(0, n-1))))
def recurrence(xs):
'''Recurrence relation in Fibonacci and related series.
'''
h, *t = xs
return h, t + [sum(xs)]
def unfoldr(f, residue):
'''Generic anamorphism.
A lazy (generator) list unfolded from a seed value by
repeated application of f until no residue remains.
Dual to fold/reduce.
f returns either None, or just (value, residue).
For a strict output value, wrap in list().
'''
while residue is not None:
value, residue = f(residue)
yield value

View file

@ -0,0 +1,46 @@
from itertools import chain
def f_rec_tailfail(values=[0, 1], combine=sum):
"""
This fails with `RecursionError: maximum recursion depth exceeded`
when the number of consumed elements surpasses maximum stack size
(by default 1000 call frames -- `sys.getrecursionlimit()`),
due to the fact that Python does not have tail call optimization.
"""
yield values[0]
yield from f_rec_tailfail(values[1:] + [combine(values)], combine)
def f_rec_gen_func(values=[0, 1], combine=sum):
"""
This function does not suffer from `RecursionError` per se, but stack overflow
nevertheless does happen in the underlying C code when too many elements are
consumed from the generator.
One possible reason for this is because `chain` is implemented in C,
and the chain consists of another `chain` object, which in turn contains
another `chain` object, etc. The effect of this is that all the recursive
calls happen on the C call stack (where recursion depth is not checked
against the limit), not on the Python call stack. As a result, it is possible
to achieve much greater recursion depth -- over 40,000 recursive calls
instead of mere 1000. When a stack overflow eventually happens, the Python
interpreter crashes quietly without any error message (CPython 3.11.3 AMD64).
"""
def generate_values():
yield [values[0]]
yield f_rec_gen_func(values[1:] + [combine(values)], combine)
return chain.from_iterable(generate_values())
def f_rec_gen_lambdas(values=[0, 1], combine=sum):
"""
Similar to `f_rec_gen_func`; also does not suffer from `RecursionError`
but crashes when many values are consumed.
"""
return chain.from_iterable(
f()
for f in (
lambda: [values[0]],
lambda: f_rec_gen_lambdas(values[1:] + [combine(values)], combine),
)
)

View file

@ -0,0 +1,35 @@
from dataclasses import dataclass, field
from functools import wraps
from typing import Callable, Generator
GeneratorFunc = Callable[..., Generator]
@dataclass
class RecursiveCall:
args: tuple = ()
kwargs: dict = field(default_factory=dict)
def tail_recursive_generator(fun: GeneratorFunc) -> GeneratorFunc:
@wraps(fun)
def decorated(*args, **kwargs):
while True:
it = fun(*args, **kwargs)
try:
while True:
yield next(it)
except StopIteration as e:
if not isinstance(res := e.value, RecursiveCall):
return res
args, kwargs = res.args, res.kwargs
return decorated
@tail_recursive_generator
def f_rec_tail(values=(0, 1), combine=sum):
"""
Does not crash or throw RecursionError! Yay!
"""
yield values[0]
# determining why we cannot call `f_rec_tail` directly
# is left as an exercise for the reader...
return RecursiveCall(args=(values[1:] + (combine(values),), combine))