Let's take an integer number, ``` start``` and let's do the iterative process described below:

- we take its digits and raise each of them to a certain power, ```n```, and add all those values up. (result = ```r1```)

- we repeat the same process with the value ```r1``` and so on, ```k``` times.

Let's do it with ```start = 420, n = 3, k = 5```

```
420 ---> 72 (= 4³ + 2³ + 0³) ---> 351 (= 7³ + 2³) ---> 153 ---> 153 ----> 153
```

We can observe that it took ```3``` steps to reach a cyclical pattern ```[153]```(```h = 3```). The length of this cyclical pattern is ```1```, ```patt_len```. The last term of our k operations is 153, ```last_term```

Now, ```start = 420, n = 4, k = 30```

```
420 ---> 272 ---> 2433 ---> 434 ---> 593 ---> 7267 --->
6114 ---> 1554 ---> 1507 ---> 3027 ---> 2498 ---> 10929 --->
13139 ---> 6725 ---> 4338 ---> 4514 ---> 1138 ---> 4179 ---> 9219 ---> 
13139 ---> 6725 ---> 4338 ---> 4514 ---> 1138 ---> 4179 ---> 9219 ---> 
13139 ---> 6725 ---> 4338 ---> 4514 ---> 1138 ---> 4179 ---> 9219......
```

In this example we can observe that the cyclical pattern (```cyc_patt_arr```) is ```[13139, 6725, 4338, 4514, 1138, 4179, 9219]``` with a length of ```7```, (```patt_len = 7```), and it took ```12``` steps (```h = 12```) to reach the cyclical pattern. The last term after doing ```30``` operations is ```1138```

Make the function ```sum_pow_dig_seq()```, that receives the arguments in the order shown below with the corresponding output:
```python
sum_pow_dig_seq(start, n, k) ---> [h, cyc_patt_arr, patt_len, last_term]
```

For our given examples, 
```python
sum_pow_dig_seq(420, 3, 5) == [3, [153], 1, 153]

sum_pow_dig_seq(420, 4, 30) == [12, [13139, 6725, 4338, 4514, 1138, 4179, 9219], 7, 1138]
```

Constraints for tests:
```
500 ≤ start ≤ 8000
2 ≤ n ≤ 9
100 * n ≤ k ≤ 200 * n
```
Do your best!

Difficulty: introductory

Starter code:

def sum_pow_dig_seq(start, n, k):
	

Solutions:
def sum_pow_dig_seq(num, exp, k):
    seq = []
    
    for step in range(k):
        seq.append(num)
        num = sum( int(dig) ** exp for dig in str(num) )
        
        if num in seq:
            cycle_start = seq.index(num)
            cycle = seq[cycle_start:]
            last_term = cycle[(k - cycle_start) % len(cycle)]
            return [ cycle_start, cycle, len(cycle), last_term ]
    
    return [ 0, [], 0, num ]

def sum_pow_dig_seq(start, n, k):
    seq = [start]
    num = start
    for i in range(k):
        num = sum([int(x)**n for x in str(num)])
        if num in seq:
            # We got the loop!
            loop_starts_from = seq.index(num)
            loop_array = seq[loop_starts_from:]
            tail_size = loop_starts_from
            loop_size = len(loop_array)
            last_term = loop_array[(k - tail_size) % loop_size]
            return [tail_size, loop_array, loop_size, last_term]
        seq.append(num)
    else:
        # What if we didn`t get the loop?
        return [len(seq), [], 0, seq[-1]]
    


def sum_pow_dig_seq(start, n, k):
    seen = [start]
    for i in range(k):
        r1 = sum(map(lambda x: x**n, map(int,str(seen[-1]))))
        if r1 in seen: #Cycle detected.
            h = seen.index(r1)
            cyc_patt_arr = seen[h:]
            patt_len = len(seen) - h
            last_term = cyc_patt_arr[(k-i-1)%patt_len]
            break
        seen.append(r1)
        
    return [h, cyc_patt_arr, patt_len, last_term]

def sum_of_digits_pow(n, e):
    return sum([i**e for i in map(int, str(n))])

def sum_pow_dig_seq(start, e, k):
    h = 0
    cyc_patt_arr, sums = [], []
    for i in range(1, k+1):
        start = sum_of_digits_pow(start, e)
        if not cyc_patt_arr and start in sums:
            cyc_patt_arr = [j for j in sums[sums.index(start):]]
            h = sums.index(start) + 1
            return [h, cyc_patt_arr, len(cyc_patt_arr), cyc_patt_arr[(k-i) % len(cyc_patt_arr)]]
        sums.append(start)
        


def sum_pow_dig_seq(start, n, k):
    def next_(v):
        return sum(int(c) ** n for c in str(v))
    
    history = []
    history_set = set()
    x = start
    while True:
        if x in history_set:
            i = history.index(x)
            cyc = history[i:]
            if k < len(history):
                return [i, cyc, len(cyc), history[k]]
            return [i, cyc, len(cyc), cyc[(k - i) % len(cyc)]]
        history.append(x)
        history_set.add(x)
        x = next_(x)

def sum_pow_dig_seq(start, n, k):
    cycle, l, h, drop = set(), [], -1, False
    for i in range(k):
        start = sum(int(d)**n for d in str(start))
        if h != -1 and start in cycle: break
        if h == -1  and start in cycle:
            cycle, h, l = set(), i, []
        cycle.add(start)
        l.append(start)
    return [h-len(l)+1, l, len(l), l[(k-i-1)%len(l)]]

def sum_pow_dig_seq(start, n, k):
    x = start
    series = []
    seen_at = {}
    i = 0
    while x not in seen_at:
        series.append(x)
        seen_at[x] = i
        x = sum(int(d) ** n for d in str(x))
        i += 1
    i_first = seen_at[x]
    cycle_length = i - i_first
    if k >= i:
        k = i_first + (k - i_first) % cycle_length
    return [i_first, series[i_first:], cycle_length, series[k]]

def sum_pow_dig_seq(start, n, k):
    r=[]
    for i in range (0,k):
       c=0
       for d in str(start):
          c+=int(d)**n
       r.append(c); start=c
    for i in range (0,k):
       if r[i] in r[i+1:]:
          posE=r.index(r[i],i+1)
          if posE>=0:
             if r[i:posE-1]==r[posE:posE+posE-1-i]: posS=i; break 
    return [posS+1, r[posS:posE], posE-posS, start]

def sum_pow_dig_seq(start, n, k):
    li = []
    for _ in range(k):
        r = sum([j ** n for j in map(int, str(start))])
        if r in li:
            reach = n = li.index(r) + 1 ; series = li[li.index(r):] ; s_l = len(series)
            while n + s_l <= k : n += s_l
            return [reach, series, s_l, series[k - n]]
        li.append(r) ; start = r

def sum_pow_dig_seq(n, e, k):
    path = [n]
    while True:
        n = sum(int(d)**e for d in str(n))
        if n in path: break
        path.append(n)
    h = path.index(n)
    loop = path[h:]
    return [h, loop, len(loop), loop[(k-h)%len(loop)]]