This kata is inspired on the problem #50 of the Project Euler. 

The prime ``` 41```  is the result of the sum of many consecutive primes.

In fact, ``` 2 + 3 + 5 + 7 + 11 + 13 = 41 , (6 addens)   ``` 

Furthermore, the prime ``` 41```  is the prime below ``` 100 (val_max)```  that has the longest chain of consecutive prime addens.

The prime with longest chain of addens for ```val_max = 500``` is ```499``` with ```17``` addens. 

In fact:
```3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61= 499```

Find the function ```prime_maxlength_chain()```(primeMaxlengthChain() javascript), that receives an argument ```val_max```, the upper limit, all the found primes should be less than ```val_max``` and outputs this found prime.

Let's see some cases:
```python
prime_maxlength_chain(100) == [41]
prime_maxlength_chain(500) == [499]
```
If we have more than one prime with these features, the function should output an array with the found primes sorted.
```python
prime_maxlength_chain(499) == [379, 491]
```
Random Tests for `val_max` (`valMax`)
```
100 ≤ val_max ≤ 500.000
```
Enjoy it!

Difficulty: introductory

Starter code:

def prime_maxlength_chain(n):
	

Solutions:
# RWH primes
LIMIT = 500000
sieve = [True] * (LIMIT//2)
for n in range(3, int(LIMIT**0.5) +1, 2):
    if sieve[n//2]: sieve[n*n//2::n] = [False] * ((LIMIT-n*n-1)//2//n +1)
PRIMES = [2] + [2*i+1 for i in range(1, LIMIT//2) if sieve[i]]


def prime_maxlength_chain(val_max):
    if val_max < 5:
        return []
    
    found = []
    
    # the sum of the first 400 primes > LIMIT
    for n in range(2, 400):
        if sum(PRIMES[:n]) >= val_max:
            max_size = n
            break
    
    for size in range(max_size, 1, -1):
        # if sequence size is even, it *must* start with 2
        if size % 2 == 0:
            n = sum(PRIMES[:size])
            if n < val_max and n in PRIMES:
                return [n]
    
        # if sequence size is odd, it *cannot* start with 2
        else:
            for start in range(1, max_size-size +1):
                n = sum(PRIMES[start:start+size])
                if n < val_max and n in PRIMES:
                    found.append(n)
            
            if found:
                return found

def is_prime(n):
    for i in range(2, int(n**0.5)+1):
        if n % i == 0:
            return False
    return True


def prime_maxlength_chain(n):

    summ, primes, res = 0, [], []

    for i in range(2, n):
        if is_prime(i):
            if summ + i < n:
                summ += i
                primes.append(i)
            elif summ + i - primes[0] < n:
                summ += i
                primes.append(i)
            else:
                break
    
    l = len(primes)

    for j in range(l, 0, -1):
        for k in range(l-j+1):
            lst = primes[k:k+j]
            temp = sum(lst)
            if is_prime(temp):
                res.append(temp)
        if len(res) != 0:
            break

    return res

from itertools import accumulate
from bisect import bisect_left
import numpy as np

limit = 555555
sieve = np.ones(limit, dtype=bool)
sieve[0] = sieve[1] = 0
sieve[2*2::2] = 0
for i in range(3, int(len(sieve)**0.5)+1, 2):
    if sieve[i]:
        sieve[i*i::i] = 0
primes = [i for i, x in enumerate(sieve) if x]
acc_primes = list(accumulate([0] + primes))
s_primes = set(primes)


def prime_maxlength_chain(n):
    limit = bisect_left(primes, n)
    ans, max_len = [], 1
    for l in range(limit):
        for r in range(l+max_len, limit+1):
            t = acc_primes[r] - acc_primes[l]
            if t >= n:
                break
            if t in s_primes and r-l >= max_len:
                ans, max_len = ([t], r-l) if r-l > max_len else (ans + [t], max_len)
    return ans

limit = 500000
sieve = [0]*2+list(range(2,limit))
for i in range(2,limit):
    for j in range(i*i,limit,i):
        sieve[j]=0
primes = [i for i in sieve if i]

def prime_maxlength_chain(n):
    req = [i for i in primes if i < n]
    P = set(req)
    D = {}
    found = []
    
    for i, j in enumerate(req):
        D[j] = [0, 0]
        for k in list(D):
            o, p = D[k]
            if o in P : found.append([o, p])
            if o + j > n:
                del D[k]
                continue
            D[k][0] += j
            D[k][1] += 1
    
    m = max(found, key=lambda x: x[1])[1]
    return [i[0] for i in found if i[1] == m]

def prime_maxlength_chain(n):
    p=[False,False]+[True]*(n-1)
    for i in range(2,n+1):
        if p[i]:
            for j in range(i*2,n+1,i):
                p[j]=False
    pn=[i for i,b in enumerate(p) if b]
    ps=set(pn)
    maxl=[0,[]]
    for l in range(6,len(pn)):
        if sum(pn[:l])>=n:
            break
        for i in range(len(pn)-l):
            s=sum(pn[i:i+l])
            if s>=n:
                break
            elif s in ps:
                if maxl[0]<l:
                    maxl=[l,[s]]
                else:
                    maxl[1].append(s)
    return maxl[1]

def prime_maxlength_chain(val_max):
   
    # Calcula os primos usando o crivo
    primes = []
    sieve = [1]*(val_max+1)
    sieve[0] = 0
    sieve[1] = 0
    for i in range(2, (val_max+1)):
        if sieve[i] == 0:
            continue
        for j in range(i*i, (val_max+1), i):
            sieve[j] = 0
           
    # Guarda os primos num array separado
    for i in range(val_max+1):
      if sieve[i] == 1:
        primes.append(i)
   
    # Testa encontrar primos que são somas de 'j' primos consecutivos    
    for j in range (400, -1, -1):
     
      # Aplica uma tecnica de janela deslizante (adicionando um cara na frente e removendo o do fundo) pra calcular mais rapido todas as janelas possiveis
      answer = []
      acc = 0
      if len(primes) < j:
        continue
     
      # Coloca os primeiros caras na janela atual
      for i in range(j):
        acc += primes[i]
     
      # Testa se eh primo
      if acc <= val_max and sieve[acc] == 1:
        answer.append(acc)
     
      # Aqui faz o procedimento de colocar o proximo cara e tirar o ultimo da janela ('deslizando' a janela pra frente)
      for i in range(j, len(primes)):
        acc += primes[i]
        acc -= primes[i-j]
        # Quando o valor ja for maior que o maximo, já pode parar
        if acc >= val_max:
          break
        # Verifica se eh primo
        if acc <= val_max and sieve[acc] == 1:
          answer.append(acc)
      # Se com o tamanho 'j' a gente encontrou resposta, a resposta eh a lista de primos com esse tamanho
      if len(answer) > 0:
        return answer


def sieve(n):
    n = n - 1 # finding primes smaller than the limit
    primes = [True for i in range(n+1)]
    result = []
    p = 2
    while p * p <= n:
        if primes[p]:
            for i in range(p * 2, n+1, p):
                primes[i] = False
        p += 1
    for p in range(2, n+1):
        if primes[p]:
            result.append(p)
    #print(result)
    return result



def prime_maxlength_chain(n):
    prime_num = sieve(n)
    prime_sums = [[0,2]]
    count_max = 0
    results = []
    if n == 0:
        return []
    i, j = 0, 0

    while sum(prime_num[i:count_max+i+j]) < n:
        while sum(prime_num[i:count_max+i+j]) < n:
            #print(prime_num[i:count_max+i+j], i, j, count_max)
            count = len(prime_num[i:count_max+i+j])
            summe = sum(prime_num[i:count_max+i+j])
            if summe in prime_num:
                prime_sums.append([count, summe])

            j += 1
        if count_max <= prime_sums[-1][0]:
            count_max = prime_sums[-1][0]
        i += 1
        j = 0
    prime_sums.sort()
    for p in prime_sums:
        if p[0] == prime_sums[-1][0]:
            results.append(p[1])


    return results

import numpy
def primesto(n):
    """ Returns a array of primes, 3 <= p < n """
    sieve = numpy.ones(n//2, dtype=numpy.bool)
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i//2]:
            sieve[i*i//2::i] = False
    return [2]+list(2*numpy.nonzero(sieve)[0][1::]+1)

def cum_sum_500k():
    return numpy.array([0]+primesto(500000)).cumsum()

def circular_list():
    p = primesto(500000)
    c = cum_sum_500k()
    l=[]
    s=1
    for i in range(400):
        for j in range(0,i-s+1):
            x=c[i]-c[j]
            #print(i,j,x)
            if x in p:
                if i-j > s: s = i-j
                #l += [[x,i-j,[p[k] for k in range(j,i)]]]
                l += [[x,i-j]]
                #print((x,s,i))
    l.sort()
    return l
#    print(p[i])

def prime_maxlength_chain(n):
    if prime_maxlength_chain.cl == []:
        prime_maxlength_chain.cl = circular_list()
    cl=prime_maxlength_chain.cl
    for i in range(len(cl)):
        idx = 0
        if cl[i][0] >= n:
            idx = i-1
            break
    l = []
    for i in range(idx,1,-1):
        if cl[i][1] == cl[idx][1]: l += [cl[i][0]]
        else: break
    l.sort()
    return l

#If you want to generate the circular primes list use cl=[] below
#prime_maxlength_chain.cl = []
prime_maxlength_chain.cl = [
[2, 1],[3, 1],[5, 2],[17, 4],[41, 6],[127, 9],[197, 12],[281, 14],[379, 15],[491, 15],[499, 17],[563, 17],[857, 19],[953, 21],[1151, 23],[1259, 25],[1361, 25],
[1583, 27],[1823, 27],[2069, 27],[2099, 29],[2399, 31],[2417, 33],[2579, 35],[2897, 35],[2909, 37],[3803, 39],[3821, 41],[4217, 43],[4421, 43],[4651, 45],[4871, 45],[5107, 47],
[5333, 47],[5813, 49],[6053, 49],[6079, 53],[6599, 55],[7699, 60],[8273, 61],[8893, 64],[9521, 65],[10181, 65],[10859, 65],[11597, 71],[12329, 71],[12713, 73],[13099, 75],[13877, 75],
[14669, 75],[15527, 79],[16823, 81],[18131, 81],[19013, 81],[21407, 85],[22037, 95],[22039, 96],[24133, 100],[25237, 102],[28087, 103],[28099, 105],[28687, 105],[28697, 108],[31729, 111],[32353, 114],
[33623, 115],[34913, 117],[36217, 117],[36871, 117],[37561, 122],[38921, 124],[41017, 125],[42451, 125],[42463, 127],[43201, 130],[44683, 132],[47711, 133],[49253, 133],[49279, 137],[52517, 141],[54167, 143],
[55837, 146],[61027, 152],[64613, 155],[66463, 158],[70241, 162],[76099, 163],[78121, 165],[78139, 167],[79151, 167],[81203, 169],[84313, 171],[86453, 178],[92951, 183],[101999, 191],[102001, 192],[109147, 198],
[115279, 201],[116531, 203],[116533, 204],[119069, 206],[121631, 208],[129419, 214],[132059, 216],[137477, 217],[138863, 219],[141671, 221],[147347, 221],[148817, 225],[153137, 225],[154579, 225],[157489, 225],[157561, 229],
[157579, 231],[162007, 231],[163483, 231],[164963, 231],[164999, 233],[166541, 237],[171131, 239],[172687, 241],[175781, 241],[178889, 241],[182009, 241],[182099, 247],[182107, 249],[198197, 251],[199831, 251],[201599, 257],
[203279, 259],[204979, 261],[210053, 261],[213461, 261],[213533, 267],[215261, 267],[218749, 269],[222269, 273],[225821, 273],[225829, 275],[240353, 279],[240371, 281],[240379, 283],[242243, 283],[244109, 283],[251609, 285],
[255443, 291],[257353, 291],[263171, 296],[269069, 297],[281023, 299],[283079, 305],[287137, 308],[303643, 309],[303691, 313],[305783, 313],[310019, 317],[314267, 317],[318557, 321],[324991, 321],[325009, 323],[325019, 326],
[329401, 328],[333821, 330],[338279, 332],[342761, 334],[351811, 335],[354097, 337],[356387, 339],[360977, 341],[360979, 342],[370261, 343],[372607, 345],[379667, 350],[393961, 356],[398771, 358],[408479, 359],[423257, 361],
[423287, 363],[425819, 365],[428339, 365],[433421, 367],[433439, 369],[438521, 369],[441101, 373],[448859, 375],[448867, 377],[477809, 377],[478001, 387],[483377, 389],[496877, 391],[499607, 393]
]