Skip to content

Instantly share code, notes, and snippets.

@EngineerCoding
Created October 25, 2018 08:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EngineerCoding/441e99366488f7229122c8a22b5b044c to your computer and use it in GitHub Desktop.
Save EngineerCoding/441e99366488f7229122c8a22b5b044c to your computer and use it in GitHub Desktop.
I needed to generate stirling numbers programmatically but couldn't find a proper implementation available in python. Being a non-mathematician, it was quite hard to understand and thus I wrote this script. From my testing, the outputs are correct.
import functools
_use_cache = True
def set_use_cache(use_cache):
global _use_cache
_use_cache = bool(use_cache)
def optional_cache(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if not _use_cache:
return func(*args, **kwargs)
key = ''
if args:
key += '@'.join(map(str, args))
if kwargs:
kwarg_names = list(kwargs.keys())
kwarg_names.sort()
if key:
key += '#'
key += '@'.join(['{}={}'.format(kwarg_key, kwargs[kwarg_key]) for kwarg_key in kwarg_keys])
if not getattr(func, 'cache', None):
setattr(func, 'cache', dict())
if key not in func.cache:
func.cache[key] = func(*args, **kwargs)
return func.cache[key]
return wrapper
@optional_cache
def first_kind(n, k):
if k == 0:
return 0
elif n == k:
return int(n != 0)
return first_kind(n - 1, k - 1) + (n - 1) * first_kind(n - 1, k)
@optional_cache
def signed_first_kind(n, k):
return first_kind(n, k) * pow(-1, n - k)
@optional_cache
def second_kind(n, k):
if n == 0 and k == 0:
return 1
elif n == 0 or k == 0:
return 0
return second_kind(n - 1, k - 1) + k * second_kind(n - 1, k)
if __name__ == '__main__':
import sys
if len(sys.argv) < 3:
print("Usage:")
print("{} {} <n:int> <k:int>".format(sys.executable, sys.argv[0]))
sys.exit(1)
def _get_int(value, name):
try:
return int(value.strip())
except ValueError:
print("argument {} is not an int: {}".format(n, value))
sys.exit(1)
n = _get_int(sys.argv[1].strip(), "n")
k = _get_int(sys.argv[2].strip(), "k")
if n <= 0:
print("n > 0 required")
sys.exit()
print("First kind unsigned: " + str(first_kind(n, k)))
print("First kind signed: " + str(signed_first_kind(n, k)))
print("Second kind: " + str(second_kind(n, k)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment