# Task:

We define the "self reversed power sequence" as one shown below:



Implement a function that takes 2 arguments (`ord max` and `num dig`), and finds the smallest term of the sequence whose index is less than or equal to `ord max`, and has exactly `num dig` number of digits.

If there is a number with correct amount of digits, the result should be an array in the form:

```python
[True, smallest found term]
[False, -1]
```

## Input range:

```python
ord_max <= 1000
```

___

## Examples:

```python
min_length_num(5, 10) == [True, 10]   # 10th term has 5 digits
min_length_num(7, 11) == [False, -1]  # no terms before the 13th one have 7 digits
min_length_num(7, 14) == [True, 13]   # 13th term is the first one which has 7 digits
```

Which you can see in the table below:

```
n-th Term    Term Value
1              0
2              1
3              3
4              8
5              22
6              65
7              209
8              732
9              2780
10             11377
11             49863
12             232768
13             1151914
14             6018785
```

___

Enjoy it and happy coding!!

Source: codewars | Difficulty: EASY
Tags: Fundamentals

Mathematics

Starter code: def min_length_num(num_dig, ord_max):
	

Solutions:
results = {}
(n, digits) = (1, 0)
while digits <= 1000:
	digits = len(str(sum((x ** (n - x + 1) for x in range(1, n)))))
	if digits not in results:
		results[digits] = n
	n += 1

def min_length_num(digits, max_num):
	n = results.get(digits, 0)
	return [True, n + 1] if n and n < max_num else [False, -1]


save = []

def min_length_num(num_dig, ord_max):
	for i in range(ord_max):
		if i == len(save):
			save.append(len(str(sum(((j + 1) ** (i - j) for j in range(i))))))
		if save[i] == num_dig:
			return [True, i + 1]
	return [False, -1]


def sequence(n):
	for i in range(n):
		s = range(i + 1)
		j = i + 1
		tot = 0
		while j > 0:
			for k in s:
				tot += k ** j
				j -= 1
			break
		yield tot
numbers = [i for i in sequence(1000)]

def min_length_num(num_dig, ord_max):
	n = 1
	for k in numbers[:ord_max]:
		if len(str(k)) == num_dig:
			return [True, n]
		elif len(str(k)) > num_dig:
			break
		n += 1
	return [False, -1]


def S(n):
	s = 0
	for i in range(1, n):
		s = s + i ** (n - i)
	return s
x = [len(str(S(n))) for n in range(1000)]

def min_length_num(num_dig, ord_max):
	y = x[1:ord_max + 1]
	if not num_dig in y:
		return [False, -1]
	for i in range(len(y) + 1):
		if y[i] >= num_dig:
			return [True, i + 1]


nums = {}

def helper():
	nums[1] = '0'
	nums[2] = '1'
	for i in range(1001):
		(exp, suma) = (1, 0)
		for j in range(i, 0, -1):
			suma += j ** exp
			exp += 1
		nums[i] = str(suma)

def min_length_num(num_dig, ord_max):
	if not nums:
		helper()
	for num in range(1, ord_max):
		if len(nums[num]) == num_dig:
			return [True, num + 1]
	return [False, -1]


def check(m):
	a = list(range(1, m + 1))
	b = a[::-1]
	c = 0
	for (x, y) in zip(a, b):
		c += x ** y
	return str(c)
lst = [1, 1] + [len(check(i)) for i in range(2, 1001)]

def min_length_num(num_dig, ord_max):
	arr = lst[:ord_max]
	if num_dig in arr:
		return [True, arr.index(num_dig) + 1]
	return [False, -1]


d = {**{0: 0, 1: 1}, **{i + 1: sum((k ** (i - k + 1) for k in range(1, i))) + i for i in range(2, 1000)}}

def min_length_num(dn, n):
	for (k, l) in d.items():
		if k > n:
			return [0, -1]
		if len(str(l)) == dn:
			return [1, k]
	return [0, -1]


import math
box = []
for n in range(1001)[1:]:
	box.append(int(math.log10(sum(map(lambda x, y: x ** y, list(range(n + 1)), sorted(list(range(n + 1)), reverse=True))))) + 1)

def min_length_num(num, ord_max):
	floor = 0
	roof = ord_max
	while floor <= roof:
		mid = (roof + floor) // 2
		if box[mid] > num:
			roof = mid - 1
		elif box[mid] < num:
			floor = mid + 1
		elif box[mid - 1] == num:
			floor -= 1
			roof -= 1
		else:
			return [True, mid + 1]
	else:
		return [False, -1]


r = [0]

def min_length_num(num_dig, ord_max):
	for n in range(1, ord_max + 1):
		if n < len(r):
			s = r[n]
		else:
			s = 0
			for i in range(1, n):
				s += i ** (n - i)
			r.append(s)
		if len(str(s)) == num_dig:
			return [True, n]
		elif len(str(s)) > num_dig:
			return [False, -1]
	return [False, -1]


def min_length_num(num_dig, ord_max):
	result = results.get(num_dig, 0)
	return [True, result + 1] if result and result < ord_max else [False, -1]
results = {}
n = 1
digit = 0
while digit < 1000:
	digit = len(str(sum((x ** (n - x + 1) for x in range(1, n)))))
	if digit not in results:
		results[digit] = n
	n += 1