Project Euler, Problem 273: finding perfect-square partitionsPerformance of modular square rootProject Euler...

Life insurance that covers only simultaneous/dual deaths

A Cautionary Suggestion

How to use deus ex machina safely?

What is a ^ b and (a & b) << 1?

What is the Japanese sound word for the clinking of money?

New passport but visa is in old (lost) passport

Shortcut for setting origin to vertice

Is it normal that my co-workers at a fitness company criticize my food choices?

What did Alexander Pope mean by "Expletives their feeble Aid do join"?

Brexit - No Deal Rejection

A formula for delta function in quantum mechanics

What is the significance behind "40 days" that often appears in the Bible?

Are ETF trackers fundamentally better than individual stocks?

How difficult is it to simply disable/disengage the MCAS on Boeing 737 Max 8 & 9 Aircraft?

What is the adequate fee for a reveal operation?

I am confused as to how the inverse of a certain function is found.

Violin - Can double stops be played when the strings are not next to each other?

How could a scammer know the apps on my phone / iTunes account?

Unexpected result from ArcLength

Recruiter wants very extensive technical details about all of my previous work

Is it true that good novels will automatically sell themselves on Amazon (and so on) and there is no need for one to waste time promoting?

If I can solve Sudoku, can I solve the Travelling Salesman Problem (TSP)? If so, how?

Did Ender ever learn that he killed Stilson and/or Bonzo?

Meme-controlled people



Project Euler, Problem 273: finding perfect-square partitions


Performance of modular square rootProject Euler Problem #6 - sum square differenceProject Euler Problem #10Project Euler 92: Square digit chainsProject Euler Problem 10Project Euler #49 Prime permutationsProject Euler Problem 11Project Euler Problem #23 (non-abundant sums)Project Euler problem #3













2












$begingroup$


Problem:




Consider equations of the form: $a^2 + b^2 = N; 0 leq a leq b; a, b, N in mathbb{N}$.



For $N=65$ there are two solutions:



$a=1, b=8$ and $a=4, b=7$.



We call $S(N)$ the sum of the values of $a$ of all solutions of $a^2 + b^2 = N$.



Thus $S(65) = 1 + 4 = 5$.



Find $sum S(N)$, for all squarefree $N$ only divisible by primes of the form $4k+1$ with $4k+1 < 150$.




My solution is painfully slow:



import math
import itertools
import time

def candidate_range(n):
cur = 5
incr = 2
while cur < n+1:
yield cur
cur += incr
incr ^= 6 # or incr = 6-incr, or however
def sieve(end):
prime_list = [2, 3]
sieve_list = [True] * (end+1)
for each_number in candidate_range(end):
if sieve_list[each_number]:
prime_list.append(each_number)
for multiple in range(each_number*each_number, end+1, each_number):
sieve_list[multiple] = False
return prime_list

primes = sieve(150)
goodprimes = []
for prime in primes:
if prime%(4)==1:
goodprimes.append(prime)
sum=[]
start_time = time.time()
#get a number that works
print("-------Part 1------")
mi=0
for L in range(1, len(goodprimes)+1):
sumf=0
for subset in itertools.combinations(goodprimes, L):
max=2**L/2
n=1
for x in subset:
n*=x

for b in range(math.floor(math.sqrt(n/2)), math.floor(math.sqrt(n)+1)):
a=math.sqrt(n-b*b)
if a.is_integer() and b>=a:
sum.append(a)
mi+=1
if mi==max:
mi=0
break
for num in sum:
sumf+=num
print(L,sumf, "--- %s seconds ---" % (time.time() - start_time))

#q+=1

print("--- %s seconds ---" % (time.time() - start_time))
sumf=0
for num in sum:
sumf+=num
print(sumf)









share|improve this question









New contributor




Alex Hal is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$












  • $begingroup$
    I find beautiful that N has 65535 values.
    $endgroup$
    – Astrinus
    2 days ago










  • $begingroup$
    .... and that you will need a BigInteger library because the topmost one will require 92 bit to be represented.
    $endgroup$
    – Astrinus
    2 days ago






  • 1




    $begingroup$
    @Astrinus Python has unlimited size integers built in.
    $endgroup$
    – mkrieger1
    yesterday










  • $begingroup$
    @mkrieger1 en.wikipedia.org/wiki/… will solve the problem better ;-)
    $endgroup$
    – Astrinus
    yesterday
















2












$begingroup$


Problem:




Consider equations of the form: $a^2 + b^2 = N; 0 leq a leq b; a, b, N in mathbb{N}$.



For $N=65$ there are two solutions:



$a=1, b=8$ and $a=4, b=7$.



We call $S(N)$ the sum of the values of $a$ of all solutions of $a^2 + b^2 = N$.



Thus $S(65) = 1 + 4 = 5$.



Find $sum S(N)$, for all squarefree $N$ only divisible by primes of the form $4k+1$ with $4k+1 < 150$.




My solution is painfully slow:



import math
import itertools
import time

def candidate_range(n):
cur = 5
incr = 2
while cur < n+1:
yield cur
cur += incr
incr ^= 6 # or incr = 6-incr, or however
def sieve(end):
prime_list = [2, 3]
sieve_list = [True] * (end+1)
for each_number in candidate_range(end):
if sieve_list[each_number]:
prime_list.append(each_number)
for multiple in range(each_number*each_number, end+1, each_number):
sieve_list[multiple] = False
return prime_list

primes = sieve(150)
goodprimes = []
for prime in primes:
if prime%(4)==1:
goodprimes.append(prime)
sum=[]
start_time = time.time()
#get a number that works
print("-------Part 1------")
mi=0
for L in range(1, len(goodprimes)+1):
sumf=0
for subset in itertools.combinations(goodprimes, L):
max=2**L/2
n=1
for x in subset:
n*=x

for b in range(math.floor(math.sqrt(n/2)), math.floor(math.sqrt(n)+1)):
a=math.sqrt(n-b*b)
if a.is_integer() and b>=a:
sum.append(a)
mi+=1
if mi==max:
mi=0
break
for num in sum:
sumf+=num
print(L,sumf, "--- %s seconds ---" % (time.time() - start_time))

#q+=1

print("--- %s seconds ---" % (time.time() - start_time))
sumf=0
for num in sum:
sumf+=num
print(sumf)









share|improve this question









New contributor




Alex Hal is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$












  • $begingroup$
    I find beautiful that N has 65535 values.
    $endgroup$
    – Astrinus
    2 days ago










  • $begingroup$
    .... and that you will need a BigInteger library because the topmost one will require 92 bit to be represented.
    $endgroup$
    – Astrinus
    2 days ago






  • 1




    $begingroup$
    @Astrinus Python has unlimited size integers built in.
    $endgroup$
    – mkrieger1
    yesterday










  • $begingroup$
    @mkrieger1 en.wikipedia.org/wiki/… will solve the problem better ;-)
    $endgroup$
    – Astrinus
    yesterday














2












2








2


0



$begingroup$


Problem:




Consider equations of the form: $a^2 + b^2 = N; 0 leq a leq b; a, b, N in mathbb{N}$.



For $N=65$ there are two solutions:



$a=1, b=8$ and $a=4, b=7$.



We call $S(N)$ the sum of the values of $a$ of all solutions of $a^2 + b^2 = N$.



Thus $S(65) = 1 + 4 = 5$.



Find $sum S(N)$, for all squarefree $N$ only divisible by primes of the form $4k+1$ with $4k+1 < 150$.




My solution is painfully slow:



import math
import itertools
import time

def candidate_range(n):
cur = 5
incr = 2
while cur < n+1:
yield cur
cur += incr
incr ^= 6 # or incr = 6-incr, or however
def sieve(end):
prime_list = [2, 3]
sieve_list = [True] * (end+1)
for each_number in candidate_range(end):
if sieve_list[each_number]:
prime_list.append(each_number)
for multiple in range(each_number*each_number, end+1, each_number):
sieve_list[multiple] = False
return prime_list

primes = sieve(150)
goodprimes = []
for prime in primes:
if prime%(4)==1:
goodprimes.append(prime)
sum=[]
start_time = time.time()
#get a number that works
print("-------Part 1------")
mi=0
for L in range(1, len(goodprimes)+1):
sumf=0
for subset in itertools.combinations(goodprimes, L):
max=2**L/2
n=1
for x in subset:
n*=x

for b in range(math.floor(math.sqrt(n/2)), math.floor(math.sqrt(n)+1)):
a=math.sqrt(n-b*b)
if a.is_integer() and b>=a:
sum.append(a)
mi+=1
if mi==max:
mi=0
break
for num in sum:
sumf+=num
print(L,sumf, "--- %s seconds ---" % (time.time() - start_time))

#q+=1

print("--- %s seconds ---" % (time.time() - start_time))
sumf=0
for num in sum:
sumf+=num
print(sumf)









share|improve this question









New contributor




Alex Hal is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$




Problem:




Consider equations of the form: $a^2 + b^2 = N; 0 leq a leq b; a, b, N in mathbb{N}$.



For $N=65$ there are two solutions:



$a=1, b=8$ and $a=4, b=7$.



We call $S(N)$ the sum of the values of $a$ of all solutions of $a^2 + b^2 = N$.



Thus $S(65) = 1 + 4 = 5$.



Find $sum S(N)$, for all squarefree $N$ only divisible by primes of the form $4k+1$ with $4k+1 < 150$.




My solution is painfully slow:



import math
import itertools
import time

def candidate_range(n):
cur = 5
incr = 2
while cur < n+1:
yield cur
cur += incr
incr ^= 6 # or incr = 6-incr, or however
def sieve(end):
prime_list = [2, 3]
sieve_list = [True] * (end+1)
for each_number in candidate_range(end):
if sieve_list[each_number]:
prime_list.append(each_number)
for multiple in range(each_number*each_number, end+1, each_number):
sieve_list[multiple] = False
return prime_list

primes = sieve(150)
goodprimes = []
for prime in primes:
if prime%(4)==1:
goodprimes.append(prime)
sum=[]
start_time = time.time()
#get a number that works
print("-------Part 1------")
mi=0
for L in range(1, len(goodprimes)+1):
sumf=0
for subset in itertools.combinations(goodprimes, L):
max=2**L/2
n=1
for x in subset:
n*=x

for b in range(math.floor(math.sqrt(n/2)), math.floor(math.sqrt(n)+1)):
a=math.sqrt(n-b*b)
if a.is_integer() and b>=a:
sum.append(a)
mi+=1
if mi==max:
mi=0
break
for num in sum:
sumf+=num
print(L,sumf, "--- %s seconds ---" % (time.time() - start_time))

#q+=1

print("--- %s seconds ---" % (time.time() - start_time))
sumf=0
for num in sum:
sumf+=num
print(sumf)






python python-3.x programming-challenge time-limit-exceeded mathematics






share|improve this question









New contributor




Alex Hal is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




Alex Hal is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited yesterday









Vogel612

21.9k447130




21.9k447130






New contributor




Alex Hal is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 2 days ago









Alex HalAlex Hal

163




163




New contributor




Alex Hal is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Alex Hal is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Alex Hal is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • $begingroup$
    I find beautiful that N has 65535 values.
    $endgroup$
    – Astrinus
    2 days ago










  • $begingroup$
    .... and that you will need a BigInteger library because the topmost one will require 92 bit to be represented.
    $endgroup$
    – Astrinus
    2 days ago






  • 1




    $begingroup$
    @Astrinus Python has unlimited size integers built in.
    $endgroup$
    – mkrieger1
    yesterday










  • $begingroup$
    @mkrieger1 en.wikipedia.org/wiki/… will solve the problem better ;-)
    $endgroup$
    – Astrinus
    yesterday


















  • $begingroup$
    I find beautiful that N has 65535 values.
    $endgroup$
    – Astrinus
    2 days ago










  • $begingroup$
    .... and that you will need a BigInteger library because the topmost one will require 92 bit to be represented.
    $endgroup$
    – Astrinus
    2 days ago






  • 1




    $begingroup$
    @Astrinus Python has unlimited size integers built in.
    $endgroup$
    – mkrieger1
    yesterday










  • $begingroup$
    @mkrieger1 en.wikipedia.org/wiki/… will solve the problem better ;-)
    $endgroup$
    – Astrinus
    yesterday
















$begingroup$
I find beautiful that N has 65535 values.
$endgroup$
– Astrinus
2 days ago




$begingroup$
I find beautiful that N has 65535 values.
$endgroup$
– Astrinus
2 days ago












$begingroup$
.... and that you will need a BigInteger library because the topmost one will require 92 bit to be represented.
$endgroup$
– Astrinus
2 days ago




$begingroup$
.... and that you will need a BigInteger library because the topmost one will require 92 bit to be represented.
$endgroup$
– Astrinus
2 days ago




1




1




$begingroup$
@Astrinus Python has unlimited size integers built in.
$endgroup$
– mkrieger1
yesterday




$begingroup$
@Astrinus Python has unlimited size integers built in.
$endgroup$
– mkrieger1
yesterday












$begingroup$
@mkrieger1 en.wikipedia.org/wiki/… will solve the problem better ;-)
$endgroup$
– Astrinus
yesterday




$begingroup$
@mkrieger1 en.wikipedia.org/wiki/… will solve the problem better ;-)
$endgroup$
– Astrinus
yesterday










2 Answers
2






active

oldest

votes


















4












$begingroup$

The code



The formatting has a number of PEP8 violations.





It's not obvious from the name what candidate_range does. It seems to be a wheel for the sieve. Normally that would be inlined in the sieve; even if you prefer not to do that, you could place the function inside sieve to make its scope clear.



I don't find sieve_list a very helpful name. In general for sieving I prefer is_composite, inverting the booleans from the way you've done it. Similarly for each_number: it reads well on the first line which uses it, but very oddly on the others.






goodprimes = []
for prime in primes:
if prime%(4)==1:
goodprimes.append(prime)



It's more Pythonic to use comprehensions:



goodprimes = [p for p in primes if p % 4 == 1]





#get a number that works



What does this mean? It looks more like noise than a useful comment to me.






for L in range(1, len(goodprimes)+1):
sumf=0
for subset in itertools.combinations(goodprimes, L):



I don't know why itertools doesn't have a function to give all subsets, but it seems like the kind of thing which is worth pulling out as a separate function, both for reuse and for readability.






        max=2**L/2



What does this do?






        n=1
for x in subset:
n*=x



Consider as an alternative



from functools import reduce
import operator

n = reduce(operator.mul, subset, 1)





        for b in range(math.floor(math.sqrt(n/2)), math.floor(math.sqrt(n)+1)):
a=math.sqrt(n-b*b)
if a.is_integer() and b>=a:



Why floors rather than ceils?



Are you certain that math.sqrt on an integer is never out by 1ULP?



Why is b>=a necessary? (Obviously b==a is impossible, and isn't the point of the range chosen to force b > a?)






                sum.append(a)



Is this for debugging? I can't see why you wouldn't just add a to a total.



NB sum is aliasing the builtin function for adding up the values in a list.






                    #q+=1



??? I can't see any other mention of q.



The algorithm



There are a few Project Euler problems which fall to brute force, but in general you need to find the right mathematical insight. Given the way this question is structured, you probably need to figure out how to find $S(n)$ given the prime factorisation of $n$.






share|improve this answer









$endgroup$





















    0












    $begingroup$

    sieve_list



    Why don't you use a generator here? It can be clearer as generator, and the candidate_range proves you know how those work.



    def sieve_OP_gen(end):
    yield 2
    yield 3
    sieve_list = [True] * (end+1)
    for each_number in candidate_range(end):
    if sieve_list[each_number]:
    yield each_number
    for multiple in range(each_number*each_number, end+1, each_number):
    sieve_list[multiple] = False


    list slice assignment



    instead of:



    for multiple in range(each_number*each_number, end+1, each_number):
    sieve_list[multiple] = False


    you can do:



    sieve_list[each_number::each_number] = [False] * (end // each_number)


    this doesn't provide any speedup, but is more clear to me



    candidate_range



    I don't like incr ^= 6. This can be done a lot clearer with itertools.cycle



    def candidate_range_maarten():
    cur = 5
    increments = itertools.cycle((2, 4))
    while True:
    yield cur
    cur += next(increments)


    But all in all I think this is a lot of effort to reduce the number of checks in generating the primes sieve by 1/3rd. In fact, it slows down the sieve generation



    def sieve2(end):
    yield 2
    sieve_list = [True] * (end + 1)
    for each_number in range(3, end + 1, 2):
    if not sieve_list[each_number]:
    continue
    yield each_number
    sieve_list[each_number::each_number] = [False] * (end // each_number)



    sieve_OP(150) == list(sieve2(150))



    True


    timings:



    %timeit sieve_OP(150)



    24.5 µs ± 1.63 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)



    %timeit list(sieve2(150))



    16.3 µs ± 124 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)



    filtering primes



    to filter the primes, you can use the builtin filter



    primes = list(sieve2(150))
    goodprimes = list(filter(lambda x: x % 4 == 1, primes))


    or a list comprehension: good_primes = [i for i in primes if i % 4 == 1]



    functions



    The rest of the code would be more clear if you split it in different functions. One to find the different candidates for the products, and another function to generate the pythagorean a



    product:



    The product of an iterable can be calculated like this:



    from functools import reduce
    from operator import mul

    def prod(iterable):
    return reduce(mul, iterable, 1)


    powerset



    As @PeterTaylor tnoted, there might be a itertools function to do this. There is,'t but there is an itertools recipe powerset:



    def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return itertools.chain.from_iterable(
    itertools.combinations(s, r) for r in range(len(s) + 1)
    )


    So generating the candidates is as easy as



    def candidates(good_primes):
    for subset in powerset(good_primes):
    yield prod(subset)


    pythagorean_a



    Instead of that nested for-loop which is not very clear what happens, I would split this to another function:



    def pythagorean_a(n):
    for a in itertools.count(1):
    try:
    b = sqrt(n - (a ** 2))
    except ValueError:
    return
    if b < a:
    return
    if b.is_integer():
    yield a



    list(pythagorean_a(65))



    [1, 4]


    bringing it together



    $S(N)$ then becomes: sum(pythagorean_a(i))



    and $sum S(N)$: sum(sum(pythagorean_a(i)) for i in candidates(good_primes))






    share|improve this answer









    $endgroup$













      Your Answer





      StackExchange.ifUsing("editor", function () {
      return StackExchange.using("mathjaxEditing", function () {
      StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
      StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
      });
      });
      }, "mathjax-editing");

      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "196"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });






      Alex Hal is a new contributor. Be nice, and check out our Code of Conduct.










      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215374%2fproject-euler-problem-273-finding-perfect-square-partitions%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      4












      $begingroup$

      The code



      The formatting has a number of PEP8 violations.





      It's not obvious from the name what candidate_range does. It seems to be a wheel for the sieve. Normally that would be inlined in the sieve; even if you prefer not to do that, you could place the function inside sieve to make its scope clear.



      I don't find sieve_list a very helpful name. In general for sieving I prefer is_composite, inverting the booleans from the way you've done it. Similarly for each_number: it reads well on the first line which uses it, but very oddly on the others.






      goodprimes = []
      for prime in primes:
      if prime%(4)==1:
      goodprimes.append(prime)



      It's more Pythonic to use comprehensions:



      goodprimes = [p for p in primes if p % 4 == 1]





      #get a number that works



      What does this mean? It looks more like noise than a useful comment to me.






      for L in range(1, len(goodprimes)+1):
      sumf=0
      for subset in itertools.combinations(goodprimes, L):



      I don't know why itertools doesn't have a function to give all subsets, but it seems like the kind of thing which is worth pulling out as a separate function, both for reuse and for readability.






              max=2**L/2



      What does this do?






              n=1
      for x in subset:
      n*=x



      Consider as an alternative



      from functools import reduce
      import operator

      n = reduce(operator.mul, subset, 1)





              for b in range(math.floor(math.sqrt(n/2)), math.floor(math.sqrt(n)+1)):
      a=math.sqrt(n-b*b)
      if a.is_integer() and b>=a:



      Why floors rather than ceils?



      Are you certain that math.sqrt on an integer is never out by 1ULP?



      Why is b>=a necessary? (Obviously b==a is impossible, and isn't the point of the range chosen to force b > a?)






                      sum.append(a)



      Is this for debugging? I can't see why you wouldn't just add a to a total.



      NB sum is aliasing the builtin function for adding up the values in a list.






                          #q+=1



      ??? I can't see any other mention of q.



      The algorithm



      There are a few Project Euler problems which fall to brute force, but in general you need to find the right mathematical insight. Given the way this question is structured, you probably need to figure out how to find $S(n)$ given the prime factorisation of $n$.






      share|improve this answer









      $endgroup$


















        4












        $begingroup$

        The code



        The formatting has a number of PEP8 violations.





        It's not obvious from the name what candidate_range does. It seems to be a wheel for the sieve. Normally that would be inlined in the sieve; even if you prefer not to do that, you could place the function inside sieve to make its scope clear.



        I don't find sieve_list a very helpful name. In general for sieving I prefer is_composite, inverting the booleans from the way you've done it. Similarly for each_number: it reads well on the first line which uses it, but very oddly on the others.






        goodprimes = []
        for prime in primes:
        if prime%(4)==1:
        goodprimes.append(prime)



        It's more Pythonic to use comprehensions:



        goodprimes = [p for p in primes if p % 4 == 1]





        #get a number that works



        What does this mean? It looks more like noise than a useful comment to me.






        for L in range(1, len(goodprimes)+1):
        sumf=0
        for subset in itertools.combinations(goodprimes, L):



        I don't know why itertools doesn't have a function to give all subsets, but it seems like the kind of thing which is worth pulling out as a separate function, both for reuse and for readability.






                max=2**L/2



        What does this do?






                n=1
        for x in subset:
        n*=x



        Consider as an alternative



        from functools import reduce
        import operator

        n = reduce(operator.mul, subset, 1)





                for b in range(math.floor(math.sqrt(n/2)), math.floor(math.sqrt(n)+1)):
        a=math.sqrt(n-b*b)
        if a.is_integer() and b>=a:



        Why floors rather than ceils?



        Are you certain that math.sqrt on an integer is never out by 1ULP?



        Why is b>=a necessary? (Obviously b==a is impossible, and isn't the point of the range chosen to force b > a?)






                        sum.append(a)



        Is this for debugging? I can't see why you wouldn't just add a to a total.



        NB sum is aliasing the builtin function for adding up the values in a list.






                            #q+=1



        ??? I can't see any other mention of q.



        The algorithm



        There are a few Project Euler problems which fall to brute force, but in general you need to find the right mathematical insight. Given the way this question is structured, you probably need to figure out how to find $S(n)$ given the prime factorisation of $n$.






        share|improve this answer









        $endgroup$
















          4












          4








          4





          $begingroup$

          The code



          The formatting has a number of PEP8 violations.





          It's not obvious from the name what candidate_range does. It seems to be a wheel for the sieve. Normally that would be inlined in the sieve; even if you prefer not to do that, you could place the function inside sieve to make its scope clear.



          I don't find sieve_list a very helpful name. In general for sieving I prefer is_composite, inverting the booleans from the way you've done it. Similarly for each_number: it reads well on the first line which uses it, but very oddly on the others.






          goodprimes = []
          for prime in primes:
          if prime%(4)==1:
          goodprimes.append(prime)



          It's more Pythonic to use comprehensions:



          goodprimes = [p for p in primes if p % 4 == 1]





          #get a number that works



          What does this mean? It looks more like noise than a useful comment to me.






          for L in range(1, len(goodprimes)+1):
          sumf=0
          for subset in itertools.combinations(goodprimes, L):



          I don't know why itertools doesn't have a function to give all subsets, but it seems like the kind of thing which is worth pulling out as a separate function, both for reuse and for readability.






                  max=2**L/2



          What does this do?






                  n=1
          for x in subset:
          n*=x



          Consider as an alternative



          from functools import reduce
          import operator

          n = reduce(operator.mul, subset, 1)





                  for b in range(math.floor(math.sqrt(n/2)), math.floor(math.sqrt(n)+1)):
          a=math.sqrt(n-b*b)
          if a.is_integer() and b>=a:



          Why floors rather than ceils?



          Are you certain that math.sqrt on an integer is never out by 1ULP?



          Why is b>=a necessary? (Obviously b==a is impossible, and isn't the point of the range chosen to force b > a?)






                          sum.append(a)



          Is this for debugging? I can't see why you wouldn't just add a to a total.



          NB sum is aliasing the builtin function for adding up the values in a list.






                              #q+=1



          ??? I can't see any other mention of q.



          The algorithm



          There are a few Project Euler problems which fall to brute force, but in general you need to find the right mathematical insight. Given the way this question is structured, you probably need to figure out how to find $S(n)$ given the prime factorisation of $n$.






          share|improve this answer









          $endgroup$



          The code



          The formatting has a number of PEP8 violations.





          It's not obvious from the name what candidate_range does. It seems to be a wheel for the sieve. Normally that would be inlined in the sieve; even if you prefer not to do that, you could place the function inside sieve to make its scope clear.



          I don't find sieve_list a very helpful name. In general for sieving I prefer is_composite, inverting the booleans from the way you've done it. Similarly for each_number: it reads well on the first line which uses it, but very oddly on the others.






          goodprimes = []
          for prime in primes:
          if prime%(4)==1:
          goodprimes.append(prime)



          It's more Pythonic to use comprehensions:



          goodprimes = [p for p in primes if p % 4 == 1]





          #get a number that works



          What does this mean? It looks more like noise than a useful comment to me.






          for L in range(1, len(goodprimes)+1):
          sumf=0
          for subset in itertools.combinations(goodprimes, L):



          I don't know why itertools doesn't have a function to give all subsets, but it seems like the kind of thing which is worth pulling out as a separate function, both for reuse and for readability.






                  max=2**L/2



          What does this do?






                  n=1
          for x in subset:
          n*=x



          Consider as an alternative



          from functools import reduce
          import operator

          n = reduce(operator.mul, subset, 1)





                  for b in range(math.floor(math.sqrt(n/2)), math.floor(math.sqrt(n)+1)):
          a=math.sqrt(n-b*b)
          if a.is_integer() and b>=a:



          Why floors rather than ceils?



          Are you certain that math.sqrt on an integer is never out by 1ULP?



          Why is b>=a necessary? (Obviously b==a is impossible, and isn't the point of the range chosen to force b > a?)






                          sum.append(a)



          Is this for debugging? I can't see why you wouldn't just add a to a total.



          NB sum is aliasing the builtin function for adding up the values in a list.






                              #q+=1



          ??? I can't see any other mention of q.



          The algorithm



          There are a few Project Euler problems which fall to brute force, but in general you need to find the right mathematical insight. Given the way this question is structured, you probably need to figure out how to find $S(n)$ given the prime factorisation of $n$.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 2 days ago









          Peter TaylorPeter Taylor

          18k2962




          18k2962

























              0












              $begingroup$

              sieve_list



              Why don't you use a generator here? It can be clearer as generator, and the candidate_range proves you know how those work.



              def sieve_OP_gen(end):
              yield 2
              yield 3
              sieve_list = [True] * (end+1)
              for each_number in candidate_range(end):
              if sieve_list[each_number]:
              yield each_number
              for multiple in range(each_number*each_number, end+1, each_number):
              sieve_list[multiple] = False


              list slice assignment



              instead of:



              for multiple in range(each_number*each_number, end+1, each_number):
              sieve_list[multiple] = False


              you can do:



              sieve_list[each_number::each_number] = [False] * (end // each_number)


              this doesn't provide any speedup, but is more clear to me



              candidate_range



              I don't like incr ^= 6. This can be done a lot clearer with itertools.cycle



              def candidate_range_maarten():
              cur = 5
              increments = itertools.cycle((2, 4))
              while True:
              yield cur
              cur += next(increments)


              But all in all I think this is a lot of effort to reduce the number of checks in generating the primes sieve by 1/3rd. In fact, it slows down the sieve generation



              def sieve2(end):
              yield 2
              sieve_list = [True] * (end + 1)
              for each_number in range(3, end + 1, 2):
              if not sieve_list[each_number]:
              continue
              yield each_number
              sieve_list[each_number::each_number] = [False] * (end // each_number)



              sieve_OP(150) == list(sieve2(150))



              True


              timings:



              %timeit sieve_OP(150)



              24.5 µs ± 1.63 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)



              %timeit list(sieve2(150))



              16.3 µs ± 124 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)



              filtering primes



              to filter the primes, you can use the builtin filter



              primes = list(sieve2(150))
              goodprimes = list(filter(lambda x: x % 4 == 1, primes))


              or a list comprehension: good_primes = [i for i in primes if i % 4 == 1]



              functions



              The rest of the code would be more clear if you split it in different functions. One to find the different candidates for the products, and another function to generate the pythagorean a



              product:



              The product of an iterable can be calculated like this:



              from functools import reduce
              from operator import mul

              def prod(iterable):
              return reduce(mul, iterable, 1)


              powerset



              As @PeterTaylor tnoted, there might be a itertools function to do this. There is,'t but there is an itertools recipe powerset:



              def powerset(iterable):
              "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
              s = list(iterable)
              return itertools.chain.from_iterable(
              itertools.combinations(s, r) for r in range(len(s) + 1)
              )


              So generating the candidates is as easy as



              def candidates(good_primes):
              for subset in powerset(good_primes):
              yield prod(subset)


              pythagorean_a



              Instead of that nested for-loop which is not very clear what happens, I would split this to another function:



              def pythagorean_a(n):
              for a in itertools.count(1):
              try:
              b = sqrt(n - (a ** 2))
              except ValueError:
              return
              if b < a:
              return
              if b.is_integer():
              yield a



              list(pythagorean_a(65))



              [1, 4]


              bringing it together



              $S(N)$ then becomes: sum(pythagorean_a(i))



              and $sum S(N)$: sum(sum(pythagorean_a(i)) for i in candidates(good_primes))






              share|improve this answer









              $endgroup$


















                0












                $begingroup$

                sieve_list



                Why don't you use a generator here? It can be clearer as generator, and the candidate_range proves you know how those work.



                def sieve_OP_gen(end):
                yield 2
                yield 3
                sieve_list = [True] * (end+1)
                for each_number in candidate_range(end):
                if sieve_list[each_number]:
                yield each_number
                for multiple in range(each_number*each_number, end+1, each_number):
                sieve_list[multiple] = False


                list slice assignment



                instead of:



                for multiple in range(each_number*each_number, end+1, each_number):
                sieve_list[multiple] = False


                you can do:



                sieve_list[each_number::each_number] = [False] * (end // each_number)


                this doesn't provide any speedup, but is more clear to me



                candidate_range



                I don't like incr ^= 6. This can be done a lot clearer with itertools.cycle



                def candidate_range_maarten():
                cur = 5
                increments = itertools.cycle((2, 4))
                while True:
                yield cur
                cur += next(increments)


                But all in all I think this is a lot of effort to reduce the number of checks in generating the primes sieve by 1/3rd. In fact, it slows down the sieve generation



                def sieve2(end):
                yield 2
                sieve_list = [True] * (end + 1)
                for each_number in range(3, end + 1, 2):
                if not sieve_list[each_number]:
                continue
                yield each_number
                sieve_list[each_number::each_number] = [False] * (end // each_number)



                sieve_OP(150) == list(sieve2(150))



                True


                timings:



                %timeit sieve_OP(150)



                24.5 µs ± 1.63 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)



                %timeit list(sieve2(150))



                16.3 µs ± 124 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)



                filtering primes



                to filter the primes, you can use the builtin filter



                primes = list(sieve2(150))
                goodprimes = list(filter(lambda x: x % 4 == 1, primes))


                or a list comprehension: good_primes = [i for i in primes if i % 4 == 1]



                functions



                The rest of the code would be more clear if you split it in different functions. One to find the different candidates for the products, and another function to generate the pythagorean a



                product:



                The product of an iterable can be calculated like this:



                from functools import reduce
                from operator import mul

                def prod(iterable):
                return reduce(mul, iterable, 1)


                powerset



                As @PeterTaylor tnoted, there might be a itertools function to do this. There is,'t but there is an itertools recipe powerset:



                def powerset(iterable):
                "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
                s = list(iterable)
                return itertools.chain.from_iterable(
                itertools.combinations(s, r) for r in range(len(s) + 1)
                )


                So generating the candidates is as easy as



                def candidates(good_primes):
                for subset in powerset(good_primes):
                yield prod(subset)


                pythagorean_a



                Instead of that nested for-loop which is not very clear what happens, I would split this to another function:



                def pythagorean_a(n):
                for a in itertools.count(1):
                try:
                b = sqrt(n - (a ** 2))
                except ValueError:
                return
                if b < a:
                return
                if b.is_integer():
                yield a



                list(pythagorean_a(65))



                [1, 4]


                bringing it together



                $S(N)$ then becomes: sum(pythagorean_a(i))



                and $sum S(N)$: sum(sum(pythagorean_a(i)) for i in candidates(good_primes))






                share|improve this answer









                $endgroup$
















                  0












                  0








                  0





                  $begingroup$

                  sieve_list



                  Why don't you use a generator here? It can be clearer as generator, and the candidate_range proves you know how those work.



                  def sieve_OP_gen(end):
                  yield 2
                  yield 3
                  sieve_list = [True] * (end+1)
                  for each_number in candidate_range(end):
                  if sieve_list[each_number]:
                  yield each_number
                  for multiple in range(each_number*each_number, end+1, each_number):
                  sieve_list[multiple] = False


                  list slice assignment



                  instead of:



                  for multiple in range(each_number*each_number, end+1, each_number):
                  sieve_list[multiple] = False


                  you can do:



                  sieve_list[each_number::each_number] = [False] * (end // each_number)


                  this doesn't provide any speedup, but is more clear to me



                  candidate_range



                  I don't like incr ^= 6. This can be done a lot clearer with itertools.cycle



                  def candidate_range_maarten():
                  cur = 5
                  increments = itertools.cycle((2, 4))
                  while True:
                  yield cur
                  cur += next(increments)


                  But all in all I think this is a lot of effort to reduce the number of checks in generating the primes sieve by 1/3rd. In fact, it slows down the sieve generation



                  def sieve2(end):
                  yield 2
                  sieve_list = [True] * (end + 1)
                  for each_number in range(3, end + 1, 2):
                  if not sieve_list[each_number]:
                  continue
                  yield each_number
                  sieve_list[each_number::each_number] = [False] * (end // each_number)



                  sieve_OP(150) == list(sieve2(150))



                  True


                  timings:



                  %timeit sieve_OP(150)



                  24.5 µs ± 1.63 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)



                  %timeit list(sieve2(150))



                  16.3 µs ± 124 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)



                  filtering primes



                  to filter the primes, you can use the builtin filter



                  primes = list(sieve2(150))
                  goodprimes = list(filter(lambda x: x % 4 == 1, primes))


                  or a list comprehension: good_primes = [i for i in primes if i % 4 == 1]



                  functions



                  The rest of the code would be more clear if you split it in different functions. One to find the different candidates for the products, and another function to generate the pythagorean a



                  product:



                  The product of an iterable can be calculated like this:



                  from functools import reduce
                  from operator import mul

                  def prod(iterable):
                  return reduce(mul, iterable, 1)


                  powerset



                  As @PeterTaylor tnoted, there might be a itertools function to do this. There is,'t but there is an itertools recipe powerset:



                  def powerset(iterable):
                  "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
                  s = list(iterable)
                  return itertools.chain.from_iterable(
                  itertools.combinations(s, r) for r in range(len(s) + 1)
                  )


                  So generating the candidates is as easy as



                  def candidates(good_primes):
                  for subset in powerset(good_primes):
                  yield prod(subset)


                  pythagorean_a



                  Instead of that nested for-loop which is not very clear what happens, I would split this to another function:



                  def pythagorean_a(n):
                  for a in itertools.count(1):
                  try:
                  b = sqrt(n - (a ** 2))
                  except ValueError:
                  return
                  if b < a:
                  return
                  if b.is_integer():
                  yield a



                  list(pythagorean_a(65))



                  [1, 4]


                  bringing it together



                  $S(N)$ then becomes: sum(pythagorean_a(i))



                  and $sum S(N)$: sum(sum(pythagorean_a(i)) for i in candidates(good_primes))






                  share|improve this answer









                  $endgroup$



                  sieve_list



                  Why don't you use a generator here? It can be clearer as generator, and the candidate_range proves you know how those work.



                  def sieve_OP_gen(end):
                  yield 2
                  yield 3
                  sieve_list = [True] * (end+1)
                  for each_number in candidate_range(end):
                  if sieve_list[each_number]:
                  yield each_number
                  for multiple in range(each_number*each_number, end+1, each_number):
                  sieve_list[multiple] = False


                  list slice assignment



                  instead of:



                  for multiple in range(each_number*each_number, end+1, each_number):
                  sieve_list[multiple] = False


                  you can do:



                  sieve_list[each_number::each_number] = [False] * (end // each_number)


                  this doesn't provide any speedup, but is more clear to me



                  candidate_range



                  I don't like incr ^= 6. This can be done a lot clearer with itertools.cycle



                  def candidate_range_maarten():
                  cur = 5
                  increments = itertools.cycle((2, 4))
                  while True:
                  yield cur
                  cur += next(increments)


                  But all in all I think this is a lot of effort to reduce the number of checks in generating the primes sieve by 1/3rd. In fact, it slows down the sieve generation



                  def sieve2(end):
                  yield 2
                  sieve_list = [True] * (end + 1)
                  for each_number in range(3, end + 1, 2):
                  if not sieve_list[each_number]:
                  continue
                  yield each_number
                  sieve_list[each_number::each_number] = [False] * (end // each_number)



                  sieve_OP(150) == list(sieve2(150))



                  True


                  timings:



                  %timeit sieve_OP(150)



                  24.5 µs ± 1.63 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)



                  %timeit list(sieve2(150))



                  16.3 µs ± 124 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)



                  filtering primes



                  to filter the primes, you can use the builtin filter



                  primes = list(sieve2(150))
                  goodprimes = list(filter(lambda x: x % 4 == 1, primes))


                  or a list comprehension: good_primes = [i for i in primes if i % 4 == 1]



                  functions



                  The rest of the code would be more clear if you split it in different functions. One to find the different candidates for the products, and another function to generate the pythagorean a



                  product:



                  The product of an iterable can be calculated like this:



                  from functools import reduce
                  from operator import mul

                  def prod(iterable):
                  return reduce(mul, iterable, 1)


                  powerset



                  As @PeterTaylor tnoted, there might be a itertools function to do this. There is,'t but there is an itertools recipe powerset:



                  def powerset(iterable):
                  "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
                  s = list(iterable)
                  return itertools.chain.from_iterable(
                  itertools.combinations(s, r) for r in range(len(s) + 1)
                  )


                  So generating the candidates is as easy as



                  def candidates(good_primes):
                  for subset in powerset(good_primes):
                  yield prod(subset)


                  pythagorean_a



                  Instead of that nested for-loop which is not very clear what happens, I would split this to another function:



                  def pythagorean_a(n):
                  for a in itertools.count(1):
                  try:
                  b = sqrt(n - (a ** 2))
                  except ValueError:
                  return
                  if b < a:
                  return
                  if b.is_integer():
                  yield a



                  list(pythagorean_a(65))



                  [1, 4]


                  bringing it together



                  $S(N)$ then becomes: sum(pythagorean_a(i))



                  and $sum S(N)$: sum(sum(pythagorean_a(i)) for i in candidates(good_primes))







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered yesterday









                  Maarten FabréMaarten Fabré

                  5,059417




                  5,059417






















                      Alex Hal is a new contributor. Be nice, and check out our Code of Conduct.










                      draft saved

                      draft discarded


















                      Alex Hal is a new contributor. Be nice, and check out our Code of Conduct.













                      Alex Hal is a new contributor. Be nice, and check out our Code of Conduct.












                      Alex Hal is a new contributor. Be nice, and check out our Code of Conduct.
















                      Thanks for contributing an answer to Code Review Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      Use MathJax to format equations. MathJax reference.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215374%2fproject-euler-problem-273-finding-perfect-square-partitions%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      is 'sed' thread safeWhat should someone know about using Python scripts in the shell?Nexenta bash script uses...

                      How do i solve the “ No module named 'mlxtend' ” issue on Jupyter?

                      Pilgersdorf Inhaltsverzeichnis Geografie | Geschichte | Bevölkerungsentwicklung | Politik | Kultur...