We are interested in collecting the triples of positive integers ```(a, b, c)``` that fulfill the following equation:
```python
a² + b² = c³
```
The first triple with the lowest values that satisfies the equation we have above is (2, 2 ,2).
In effect:
```python
2² + 2² = 2³
4  + 4  = 8
```
The first pair of triples that "shares" the same value of ```c``` is: ```(2, 11, 5)``` and ```(5, 10, 5)```. 

Both triples share the same value of ```c```  is ```c = 5```. 
```python
Triple (2, 11, 5)                  Triple(5, 10, 5)
2² + 11² =  5³                      5² +  10²  =  5³
4  + 121 = 125                     25  + 100   = 125
```
So, we say that the value ```c``` has two solutions because there are two triples sharing the same value of ```c```.

There are some values of ```c``` with no solutions.

The first value of ```c``` that have a surprising number of solutions is ```65``` with ```8``` different triples.

In order to avoid duplications you will consider that ```a <= b``` always.

Make the function ```find_abc_sumsqcube()```, that may give us the values of c for an specific number of solutions.

For that purpose the above required function will receive two arguments, ```c_max``` and ```num_sol```. It is understandable that ```c_max``` will give to our function the upper limit of ```c``` and ```num_sol```, the specific number of solutions.

The function will output a sorted list with the values of ```c``` that have a number of solutions equals to ```num_sol```

Let's see some cases: 
```python
find_abc_sumsqcube(5, 1) == [2] # below or equal to c_max = 5 we have triple the (2, 2, 2) (see above)

find_abc_sumsqcube(5, 2) == [5] # now we want the values of ```c ≤ c_max``` with two solutions (see above again)

find_abc_sumsqcube(10, 2) == [5, 10]

find_abc_sumsqcube(20, 8) == [] # There are no values of c equal and bellow 20 having 8 solutions.
```

Our tests will have the following ranges for our two arguments:
```python
5 ≤ c_max ≤ 1000
1 ≤ num_sol ≤ 10
```
Happy coding!!

Source: codewars | Difficulty: EASY
Tags: Dynamic programming

Fundamentals

Data structures

Mathematics

Starter code: def find_abc_sumsqcube(c_max, num_sol):
	

Solutions:
from bisect import bisect_right as bisect
RES = [[] for _ in range(11)]
for c in range(1, 1001):
	c3 = c ** 3
	nSol = sum((((c3 - a ** 2) ** 0.5).is_integer() for a in range(1, int((c3 // 2) ** 0.5 + 1))))
	if 0 < nSol < 11:
		RES[nSol].append(c)

def find_abc_sumsqcube(c_max, nSol):
	return RES[nSol][:bisect(RES[nSol], c_max)]


from math import sqrt

def nb_sol_cube_is_sumsq(c):
	count = 0
	c3 = c ** 3
	modc3 = c3 % 4
	if modc3 == 3 or modc3 == 2:
		return 0
	for a in range(1, int(sqrt(c ** 3)) + 1):
		b = sqrt(c3 - a ** 2)
		if int(b) == b and 0 < b <= a:
			count += 1
	return count

def nb_abc_sol(c_max):
	(res, c) = ([], 1)
	while c <= c_max:
		res.append(nb_sol_cube_is_sumsq(c))
		c += 1
	return res
sol = nb_abc_sol(1001)

def find_abc_sumsqcube(c_max, num_sol):
	return [i + 1 for (i, count) in enumerate(sol[:c_max]) if count == num_sol]


from bisect import bisect_right
from math import sqrt
SOL = [[] for _ in range(11)]
for c in range(1, 1001):
	c3 = c ** 3
	num_sol = sum((sqrt(c3 - a ** 2).is_integer() for a in range(1, int(sqrt(c3 // 2) + 1))))
	if 0 < num_sol < 11:
		SOL[num_sol].append(c)

def find_abc_sumsqcube(c_max, num_sol):
	res = SOL[num_sol]
	return res[:bisect_right(res, c_max)]


dic1 = {1: [2, 8, 18, 32, 72, 98, 128, 162, 242, 288, 392, 512, 648, 722, 882, 968], 2: [5, 10, 13, 17, 20, 26, 29, 34, 37, 40, 41, 45, 52, 53, 58, 61, 68, 73, 74, 80, 82, 89, 90, 97, 101, 104, 106, 109, 113, 116, 117, 122, 136, 137, 146, 148, 149, 153, 157, 160, 164, 173, 178, 180, 181, 193, 194, 197, 202, 208, 212, 218, 226, 229, 232, 233, 234, 241, 244, 245, 257, 261, 269, 272, 274, 277, 281, 292, 293, 296, 298, 306, 313, 314, 317, 320, 328, 333, 337, 346, 349, 353, 356, 360, 362, 369, 373, 386, 388, 389, 394, 397, 401, 404, 405, 409, 416, 421, 424, 433, 436, 449, 452, 457, 458, 461, 464, 466, 468, 477, 482, 488, 490, 509, 514, 521, 522, 538, 541, 544, 548, 549, 554, 557, 562, 569, 577, 584, 586, 592, 593, 596, 601, 605, 612, 613, 617, 626, 628, 634, 637, 640, 641, 653, 656, 657, 661, 666, 673, 674, 677, 692, 698, 701, 706, 709, 712, 720, 724, 733, 738, 746, 757, 761, 769, 772, 773, 776, 778, 788, 794, 797, 801, 802, 808, 809, 810, 818, 821, 829, 832, 833, 842, 848, 853, 857, 866, 872, 873, 877, 881, 898, 904, 909, 914, 916, 922, 928, 929, 932, 936, 937, 941, 953, 954, 964, 976, 977, 980, 981, 997], 3: [25, 100, 169, 225, 289, 400, 676, 841, 900], 4: [50, 200, 338, 450, 578, 800], 8: [65, 85, 130, 145, 170, 185, 205, 221, 260, 265, 290, 305, 340, 365, 370, 377, 410, 442, 445, 481, 485, 493, 505, 520, 530, 533, 545, 565, 580, 585, 610, 629, 680, 685, 689, 697, 730, 740, 745, 754, 765, 785, 793, 820, 865, 884, 890, 901, 905, 949, 962, 965, 970, 985, 986], 5: [125, 250, 500, 1000], 14: [325, 425, 650, 725, 845, 850, 925], 6: [625]}
import bisect

def find_abc_sumsqcube(c_max, num_sol):
	if num_sol not in dic1.keys():
		return []
	lst = dic1[num_sol]
	idx = bisect.bisect_right(lst, c_max)
	return lst[:idx]


import math
from functools import lru_cache

@lru_cache(maxsize=1024)
def solutions(c):
	cube = c ** 3
	return sum((1 for a in range(1, int((cube // 2) ** 0.5) + 1) if ((cube - a ** 2) ** 0.5).is_integer()))

def find_abc_sumsqcube(c_max, num_sol):
	result = []
	for c in range(2, c_max + 1):
		if solutions(c) == num_sol:
			result.append(c)
	return result