Generate and return **all** possible increasing arithmetic progressions of six primes `[a, b, c, d, e, f]` between the given limits. Note: the upper and lower limits are inclusive.

An arithmetic progression is a sequence where the difference between consecutive numbers is the same, such as: 2, 4, 6, 8.

A prime number is a number that is divisible only by itself and 1 (e.g. 2, 3, 5, 7, 11)

Your solutions should be returned as lists inside a list in ascending order of the first item (if there are multiple lists with same first item, return in ascending order for the second item etc) are the e.g: `[ [a, b, c, d, e, f], [g, h, i, j, k, l] ]` where `a < g`. If there are no solutions, return an empty list: `[]`

## Examples

Difficulty: introductory

Starter code:

def primes_a_p(lower_limit, upper_limit):
	

Solutions:
is_prime = lambda n: all(n % d for d in range(3, int(n ** .5) + 1, 2))

def primes_a_p(lower_limit, upper_limit):
    a_p = []
    for n in range(lower_limit | 1, upper_limit, 2):
        for gap in range(30, (upper_limit - n) // 5 + 1, 30):
            sequence = [n + i * gap for i in range(6)]
            if all(map(is_prime, sequence)):
                a_p.append(sequence)
    return a_p

limit = 10_000
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 primes_a_p(l, u):
    li, found = sorted([i for i in primes if l<=i<=u]), []
    
    for i, a in enumerate(li):
        for b in li[i+1:]:
            diff, tray = b-a, [a, b]

            for _ in range(4):
                c = tray[-1] + diff
                if c in primes and c < u:
                    tray.append(c)
                    continue
                break
                    
            if len(tray)==6:
                found.append(tray)
            
    return found

from itertools import combinations, compress
import numpy as np

s = np.ones(100000)
s[:2] = s[2::2] = 0
for i in range(3, int(len(s)**0.5)+1, 2):
    if s[i]:
        s[i*i::i] = 0
primes = list(compress(range(len(s)), s))

def primes_a_p(lower_limit, upper_limit):
    xs = primes[np.searchsorted(primes, lower_limit):np.searchsorted(primes, upper_limit)]
    return [
        list(range(a, a+6*(b-a), b-a))
        for a, b in combinations(xs, 2)
        if all(x <= upper_limit and s[x] for x in range(b+b-a, a+6*(b-a), b-a))
    ]

from bisect import *

n=10000
sieve, PRIMES = [0]*(n+1), []
for i in range(2, n+1):
    if not sieve[i]:
        PRIMES.append(i) 
        for j in range(i**2, n+1, i): sieve[j] = 1
        
def primes_a_p(low, high):
    subPrimes = PRIMES[bisect_left(PRIMES,low):bisect_right(PRIMES,high)]
    ans, sP   = [], set(subPrimes)
    
    for i,p in enumerate(subPrimes):
        for q in subPrimes[i+1:]:
            d = q-p
            prog = [p+d*n for n in range(6)]
            if set(prog) <= sP: ans.append(prog)
    return ans


LIMIT = 10**4
sieve = list(range(LIMIT))
sieve[1] = 0
primes = []
for n in sieve:
    if n:
        primes.append(n)
        for i in range(n*n, LIMIT, n):
            sieve[i] = 0

del sieve
primes.remove(2)


def primes_a_p(lower_limit, upper_limit, k=6):
    primes_list = [ p for p in primes if lower_limit <= p <= upper_limit ]
    primes_set = set(primes_list)
    
    max_scope = (upper_limit - lower_limit) // (k-1)
    
    #base_diff = reduce(mul, [ p for p in primes if p <= k ])
    base_diff = 2 * 3 * 5
    
    solutions = []
    
    for n in range(1, max_scope // base_diff + 1):
        diffs = [ n * base_diff * x for x in range(k) ]
        scope = n * base_diff * (k-1)
        
        for p in primes_list:
            if p + scope > upper_limit:
                break
            
            if { p+d for d in diffs } <= primes_set:
                solutions.append([ p + d for d in diffs ])
    
    return sorted(solutions)

def primes1(n):
    sieve = [True] * n
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i]:
            sieve[i*i::2*i]=[False]*((n-i*i-1)//(2*i)+1)
    return [2] + [i for i in range(3,n,2) if sieve[i]]

lst = primes1(10000)

import bisect
def primes_a_p(lower_limit, upper_limit):
    lst0 = lst[bisect.bisect_left(lst, lower_limit):bisect.bisect_right(lst,upper_limit)]
    ans = []
    for i in range(len(lst0)-5):
        for j in range(30, upper_limit//5, 30):
            x = lst0[i]+j
            if x not in lst0:
                continue
            if x > lst0[-1]:
                break
            temp = [lst0[i], x]
            flag = True
            while len(temp) < 6:
                x += j
                if x in lst0:
                    temp.append(x)
                else:
                    flag = False
                    break
            if flag == True:
                ans.append(temp)
    return ans

def primes1(n):
    sieve = [True] * n
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i]:
            sieve[i*i::2*i]=[False]*((n-i*i-1)//(2*i)+1)
    return [2] + [i for i in range(3,n,2) if sieve[i]]

lst = primes1(10000)

import bisect
def primes_a_p(lower_limit, upper_limit):
    lst0 = lst[bisect.bisect_left(lst, lower_limit):bisect.bisect_right(lst,upper_limit)]
    ans = []
    for i in range(len(lst0)-5):
        for j in range(30, 1500, 30):
            x = lst0[i]+j
            if x not in lst0:
                continue
            if x > lst0[-1]:
                break
            temp = [lst0[i], x]
            flag = True
            while len(temp) < 6:
                x += j
                if x in lst0:
                    temp.append(x)
                else:
                    flag = False
                    break
            if flag == True:
                ans.append(temp)
    return ans
                 


def sito(m, n):
    """Sito Erastotenesa"""
    numbers = [x for x in range(0, n+1)]
    numbers[0], numbers[1] = False, False
    primes = {}
    for i,x in enumerate(numbers):
        if x:
            if x >= m:
                primes[x] = x
            index = i**2
            while index < len(numbers):
                numbers[index] = False
                index += x
    return primes
                

def primes_a_p(lower_limit, upper_limit):
    primes = sito(lower_limit, upper_limit)
    longest_gap = (upper_limit-lower_limit) // 5
    ap_primes = []
    for i in list(primes.keys()):
        for gap in range(2,longest_gap, 2):
        
            if primes[i]+5*gap <= upper_limit:
                check = [primes[i]+n*gap for n in range(0,6)]
                if any(num not in primes for num in check):
                    pass
                else:
                    ap_primes.append(check)
    return ap_primes


from math import sqrt

def primes_a_p(lower_limit, upper_limit):
    
    primes = [p for p in prime_sieve(upper_limit + 1) if p >= lower_limit]
    
    res = []
    
    for k in range(30, upper_limit // 5, 30):
        terms = [0, k, 2 * k, 3 * k, 4 * k, 5 * k]
        for p in primes: 
            pp = [t + p for t in terms]
            
            if all(t in primes for t in pp): 
                res.append(pp)
                
    return sorted(res, key = lambda v: v[0])

def prime_sieve(n):
    sieve = [True] * n
    for i in range(3, int(sqrt(n)) + 1, 2):
        if sieve[i]:
            sieve[i * i::2 * i]= [False] * ((n - i * i - 1) // (2 * i) + 1)
    return [2] + [i for i in range(3, n, 2) if sieve[i]]