Given a non-negative number, return the next bigger polydivisible number, or an empty value like `null` or `Nothing`.

A number is polydivisible if its first digit is cleanly divisible by `1`, its first two digits by `2`, its first three by `3`, and so on. There are finitely many polydivisible numbers.

Source: codewars | Difficulty: EASY

Starter code: def next_num(n):
	

Solutions:
(d, polydivisible, arr) = (1, [], list(range(1, 10)))
while arr:
	d += 1
	polydivisible.extend(arr)
	arr = [n for x in arr for n in range(-(-x * 10 // d) * d, (x + 1) * 10, d)]

def next_num(n):
	from bisect import bisect
	idx = bisect(polydivisible, n)
	if idx < len(polydivisible):
		return polydivisible[idx]


def next_num(n):

	def dfs(m=0, i=0, fromZ=0):
		if m > n:
			yield m
		elif i < len(s):
			m *= 10
			for d in range(0 if fromZ else s[i], 10):
				if not (m + d) % (i + 1):
					yield from dfs(m + d, i + 1, fromZ or d > s[i])
	s = list(map(int, str(n)))
	ret = next(dfs(), None)
	if ret is None:
		s = [1] + [0] * len(s)
		ret = next(dfs(), None)
	return ret


import requests
from bisect import bisect
MAGIC = [int(x) for x in requests.get('https://oeis.org/b144688.txt').text.split()[1::2]]

def next_num(n):
	return MAGIC[bisect(MAGIC, n)] if n < MAGIC[-1] else None


def f(xs, i, changed):
	if i and int(''.join(map(str, xs[:i]))) % i:
		return
	if i == len(xs):
		return int(''.join(map(str, xs)))
	prev = xs[i]
	for x in range(0 if changed else prev, 10):
		xs[i] = x
		res = f(xs, i + 1, changed or x != prev)
		if res:
			return res
	xs[i] = prev

def next_num(n):
	res = f(list(map(int, str(n + 1))), 0, False)
	if res:
		return res
	s = '1' + '0' * len(str(n))
	return f(list(map(int, s)), 0, False)


def next_num(n):
	mpl = 25
	lpn = 3608528850368400786036725
	if n >= lpn:
		return None
	nl = len(str(n))
	extend = {}
	for i in range(1, mpl + 2):
		if i % 10 == 0:
			extend[i] = {'0'}
		elif i % 5 == 0:
			extend[i] = {'0', '5'}
		elif i % 2 == 0:
			extend[i] = {'0', '2', '4', '6', '8'}
		else:
			extend[i] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
	d = {1: {'1', '2', '3', '4', '5', '6', '7', '8', '9'}}
	for l in range(2, 2 + nl):
		d[l] = {p + i for i in extend[l] for p in d[l - 1] if int(p + i) % l == 0}
	d[1].add('0')
	if n >= max(map(int, d[nl])):
		return min(map(int, d[nl + 1]))
	else:
		for i in sorted(map(int, d[nl])):
			if i > n:
				return i


def polydivisible(n):
	len_n = len(str(n))
	for i in range(1, len_n + 1):
		if n // 10 ** (len_n - i) % i != 0:
			return i
	else:
		return True

def next_num(n):
	n += 1
	while n <= 3608528850368400786036725:
		pr = polydivisible(n)
		if pr == True:
			return n
		else:
			len_n = len(str(n))
			num = 10 ** (len_n - pr)
			n = (n // num + 1) * num


from bisect import bisect
rec = lambda L, i: L and L + rec([y for x in L for y in range(10 * x, 10 * (x + 1)) if not y % i], i + 1)
polys = rec(list(range(1, 10)), 2)

def next_num(n):
	try:
		return polys[bisect(polys, n)]
	except IndexError:
		return


def find_polydivisible(digits_limit):
	numbers = []
	previous = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
	digits = 2
	poly_for_digits = []
	while previous and digits <= digits_limit:
		numbers += previous
		for p in previous:
			for i in range(10):
				number = p * 10 + i
				if number % digits == 0:
					poly_for_digits.append(number)
		previous = poly_for_digits[:]
		poly_for_digits = []
		digits += 1
	return numbers
polydivisibles = find_polydivisible(26)

def next_num(n):
	return next((p for p in polydivisibles if p >= n + 1), None)


def next_num(n):
	n += 1
	while n <= 3608528850368400786036725:
		pr = ifpol(n)
		if pr == True:
			return n
		else:
			s = len(str(n))
			num = 10 ** (s - pr)
			n = (n // num + 1) * num

def ifpol(n):
	s = len(str(n))
	for i in range(1, s + 1):
		if n // 10 ** (s - i) % i != 0:
			return i
	return True


def next_num(n):
	number = str(n + 1)

	def isNumPoly(number):
		for i in range(1, len(number) + 1):
			if not int(number[0:i]) % i == 0:
				return i
		return 0
	while int(number) < 3610000000000000000000000:
		where = isNumPoly(number)
		if where == 0:
			return int(number)
		badPiece = number[0:where]
		replacement = str(int(badPiece) + (where - int(badPiece) % where))
		number = replacement + '0' * len(number[where:])
	return None