# 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!!

Difficulty: introductory

Starter code:

def min_length_num(num_dig, ord_max):
	

Solutions:
# precalculate results
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