Project Euler #641 Python 3.6 - Numpy











up vote
1
down vote

favorite
1












I'm working on solve the below problem from Project Euler, which in short deals with iterating over 'n' dice and updating their values.




A Long Row of Dice - project Euler problem #641



Consider a row of n dice all showing 1.



First turn every second die,(2,4,6,…), so that the number showing is increased by 1. Then turn every third die. The sixth die will now show a 3. Then turn every fourth die and so on until every nth die (only the last die) is turned. If the die to be turned is showing a 6 then it is changed to show a 1.



Let f(n) be the number of dice that are showing a 1 when the process finishes. You are given f(100)=2 and f(10^8)=69.



Find f(10^36).




I've written the below code in Python using numpy, but can't exactly figure out what I'm doing wrong to my function output to match the output above. Right now f(100) returns 1 (should be 2); even f(1000) returns 1.



import numpy as np

def f(n):
# establish dice and the value sets for the dice
dice = np.arange(1, n + 1)
dice_values = np.ones(len(dice))
turns = range(2, len(dice) + 1)
print("{a} dice, {b} values, {c} runs to process".format(a=len(dice), b=len(dice_values), c=len(turns)))

# iterate and update the values of each die
# in our array of dice
for turn in turns:
# if die to be processed is 6, update to 1
dice_values[(dice_values == 6) & (dice % turn == 0)] = 1

# update dice_values to if the die's index has no remainder
# from the turn we're processing.
dice_values += dice % turn == 0

# output status
print('Processed every {0} dice'.format(turn))
print('{0}nn'.format(dice_values))
return "f({n}) = {x}".format(n=n, x=len(np.where(dice_values == 1)))




UPDATE 11/12/18



@Prune's guidance has been extremely helpful. My methodology is now as follows:




  • Find all the squares from 1 to n.


  • Find all squares with a number of factors which have a remainder of 1, when dividing by 6.



    import numpy as np


    # brute force to find number of factors for each n
    def factors(n):
    result =
    i = 1
    # This will loop from 1 to int(sqrt(n))
    while i * i <= n:
    # Check if i divides x without leaving a remainder
    if n % i == 0:
    result.append(i)
    if n / i != i:
    result.append(n / i)
    i += 1
    # Return the list of factors of x
    return len(result)


    vect_factors = np.vectorize(factors)


    # avoid brute forcing all numbers
    def f(n):
    # create an array of 1 to n + 1
    # find all perfect squares in that range
    dice = np.arange(1, n + 1)[(np.mod(np.sqrt(np.arange(1, n + 1)), 1) == 0)]
    # find all squares which have n-factors, which
    # when divided by 6 have a remainder of 1.
    dice = dice[np.mod(vect_factors(dice), 6) == 1]
    return len(dice)



Worth noting - on my machine, I'm unable to run larger than 10^10. While solving this would be ideal, I feel that what I've learned (and determined how to apply) in the process is enough for me.





UPDATE 11/13/2018



I'm continuing to spend a small bit of time trying to optimize this to get it processing more quickly. Here's the updated code base. This evaluates f(10**10) in 1 min and 17 seconds.



import time
from datetime import timedelta
import numpy as np
import math

from itertools import chain, cycle, accumulate


def find_squares(n):
return np.array([n ** 2 for n in np.arange(1, highest = math.sqrt(n) + 1)])

# brute force to find number of factors for each n
def find_factors(n):
def prime_powers(n):
# c goes through 2, 3, 5, then the infinite (6n+1, 6n+5) series
for c in accumulate(chain([2, 1, 2], cycle([2, 4]))):
if c * c > n: break
if n % c: continue
d, p = (), c
while not n % c:
n, p, d = n // c, p * c, d + (p,)
yield (d)
if n > 1: yield ((n,))

r = [1]
for e in prime_powers(n):
r += [a * b for a in r for b in e]
return len(r)


vect_factors = np.vectorize(find_factors)


# avoid brute forcing all numbers
def f(n):
# create an array of 1 to n + 1
# find all perfect squares in that range
start = time.time()
dice = find_squares(n)
# find all squares which have n-factors, which
# when divided by 6 have a remainder of 1.
dice = dice[np.mod(vect_factors(dice), 6) == 1]
diff = (timedelta(seconds=int(time.time() - start))).__str__()
print("{n} has {remain} dice with a value of 1. Computed in {diff}.".format(n=n, remain=len(dice), diff=diff))









share|improve this question




















  • 2




    If your dice shows a 6 and has to be turned, you turn it first to 1, then again to 2. You'd rather add 1, then turn the 7 to 1, or use a modulo. Anyway, bruteforcing it won't help for f(10^36), you will have to do some maths...
    – Thierry Lathuille
    Nov 9 at 21:52










  • When you get to a resolution, please remember to up-vote useful things and accept your favourite answer (even if you have to write it yourself), so Stack Overflow can properly archive the question.
    – Prune
    Nov 12 at 18:43










  • Worth noting, on my machine the code from UPDATE 11/12/18 performs fairly well on 10^8, but begins breaking down at 10^9. f(10**8) -> 100000000 has 69 dice with a value of 1. Computed in 0:00:21. f(10**9) -> 1000000000 has 124 dice with a value of 1. Computed in 0:05:06. @Prune thanks for the help!
    – rs311
    Nov 12 at 22:25

















up vote
1
down vote

favorite
1












I'm working on solve the below problem from Project Euler, which in short deals with iterating over 'n' dice and updating their values.




A Long Row of Dice - project Euler problem #641



Consider a row of n dice all showing 1.



First turn every second die,(2,4,6,…), so that the number showing is increased by 1. Then turn every third die. The sixth die will now show a 3. Then turn every fourth die and so on until every nth die (only the last die) is turned. If the die to be turned is showing a 6 then it is changed to show a 1.



Let f(n) be the number of dice that are showing a 1 when the process finishes. You are given f(100)=2 and f(10^8)=69.



Find f(10^36).




I've written the below code in Python using numpy, but can't exactly figure out what I'm doing wrong to my function output to match the output above. Right now f(100) returns 1 (should be 2); even f(1000) returns 1.



import numpy as np

def f(n):
# establish dice and the value sets for the dice
dice = np.arange(1, n + 1)
dice_values = np.ones(len(dice))
turns = range(2, len(dice) + 1)
print("{a} dice, {b} values, {c} runs to process".format(a=len(dice), b=len(dice_values), c=len(turns)))

# iterate and update the values of each die
# in our array of dice
for turn in turns:
# if die to be processed is 6, update to 1
dice_values[(dice_values == 6) & (dice % turn == 0)] = 1

# update dice_values to if the die's index has no remainder
# from the turn we're processing.
dice_values += dice % turn == 0

# output status
print('Processed every {0} dice'.format(turn))
print('{0}nn'.format(dice_values))
return "f({n}) = {x}".format(n=n, x=len(np.where(dice_values == 1)))




UPDATE 11/12/18



@Prune's guidance has been extremely helpful. My methodology is now as follows:




  • Find all the squares from 1 to n.


  • Find all squares with a number of factors which have a remainder of 1, when dividing by 6.



    import numpy as np


    # brute force to find number of factors for each n
    def factors(n):
    result =
    i = 1
    # This will loop from 1 to int(sqrt(n))
    while i * i <= n:
    # Check if i divides x without leaving a remainder
    if n % i == 0:
    result.append(i)
    if n / i != i:
    result.append(n / i)
    i += 1
    # Return the list of factors of x
    return len(result)


    vect_factors = np.vectorize(factors)


    # avoid brute forcing all numbers
    def f(n):
    # create an array of 1 to n + 1
    # find all perfect squares in that range
    dice = np.arange(1, n + 1)[(np.mod(np.sqrt(np.arange(1, n + 1)), 1) == 0)]
    # find all squares which have n-factors, which
    # when divided by 6 have a remainder of 1.
    dice = dice[np.mod(vect_factors(dice), 6) == 1]
    return len(dice)



Worth noting - on my machine, I'm unable to run larger than 10^10. While solving this would be ideal, I feel that what I've learned (and determined how to apply) in the process is enough for me.





UPDATE 11/13/2018



I'm continuing to spend a small bit of time trying to optimize this to get it processing more quickly. Here's the updated code base. This evaluates f(10**10) in 1 min and 17 seconds.



import time
from datetime import timedelta
import numpy as np
import math

from itertools import chain, cycle, accumulate


def find_squares(n):
return np.array([n ** 2 for n in np.arange(1, highest = math.sqrt(n) + 1)])

# brute force to find number of factors for each n
def find_factors(n):
def prime_powers(n):
# c goes through 2, 3, 5, then the infinite (6n+1, 6n+5) series
for c in accumulate(chain([2, 1, 2], cycle([2, 4]))):
if c * c > n: break
if n % c: continue
d, p = (), c
while not n % c:
n, p, d = n // c, p * c, d + (p,)
yield (d)
if n > 1: yield ((n,))

r = [1]
for e in prime_powers(n):
r += [a * b for a in r for b in e]
return len(r)


vect_factors = np.vectorize(find_factors)


# avoid brute forcing all numbers
def f(n):
# create an array of 1 to n + 1
# find all perfect squares in that range
start = time.time()
dice = find_squares(n)
# find all squares which have n-factors, which
# when divided by 6 have a remainder of 1.
dice = dice[np.mod(vect_factors(dice), 6) == 1]
diff = (timedelta(seconds=int(time.time() - start))).__str__()
print("{n} has {remain} dice with a value of 1. Computed in {diff}.".format(n=n, remain=len(dice), diff=diff))









share|improve this question




















  • 2




    If your dice shows a 6 and has to be turned, you turn it first to 1, then again to 2. You'd rather add 1, then turn the 7 to 1, or use a modulo. Anyway, bruteforcing it won't help for f(10^36), you will have to do some maths...
    – Thierry Lathuille
    Nov 9 at 21:52










  • When you get to a resolution, please remember to up-vote useful things and accept your favourite answer (even if you have to write it yourself), so Stack Overflow can properly archive the question.
    – Prune
    Nov 12 at 18:43










  • Worth noting, on my machine the code from UPDATE 11/12/18 performs fairly well on 10^8, but begins breaking down at 10^9. f(10**8) -> 100000000 has 69 dice with a value of 1. Computed in 0:00:21. f(10**9) -> 1000000000 has 124 dice with a value of 1. Computed in 0:05:06. @Prune thanks for the help!
    – rs311
    Nov 12 at 22:25















up vote
1
down vote

favorite
1









up vote
1
down vote

favorite
1






1





I'm working on solve the below problem from Project Euler, which in short deals with iterating over 'n' dice and updating their values.




A Long Row of Dice - project Euler problem #641



Consider a row of n dice all showing 1.



First turn every second die,(2,4,6,…), so that the number showing is increased by 1. Then turn every third die. The sixth die will now show a 3. Then turn every fourth die and so on until every nth die (only the last die) is turned. If the die to be turned is showing a 6 then it is changed to show a 1.



Let f(n) be the number of dice that are showing a 1 when the process finishes. You are given f(100)=2 and f(10^8)=69.



Find f(10^36).




I've written the below code in Python using numpy, but can't exactly figure out what I'm doing wrong to my function output to match the output above. Right now f(100) returns 1 (should be 2); even f(1000) returns 1.



import numpy as np

def f(n):
# establish dice and the value sets for the dice
dice = np.arange(1, n + 1)
dice_values = np.ones(len(dice))
turns = range(2, len(dice) + 1)
print("{a} dice, {b} values, {c} runs to process".format(a=len(dice), b=len(dice_values), c=len(turns)))

# iterate and update the values of each die
# in our array of dice
for turn in turns:
# if die to be processed is 6, update to 1
dice_values[(dice_values == 6) & (dice % turn == 0)] = 1

# update dice_values to if the die's index has no remainder
# from the turn we're processing.
dice_values += dice % turn == 0

# output status
print('Processed every {0} dice'.format(turn))
print('{0}nn'.format(dice_values))
return "f({n}) = {x}".format(n=n, x=len(np.where(dice_values == 1)))




UPDATE 11/12/18



@Prune's guidance has been extremely helpful. My methodology is now as follows:




  • Find all the squares from 1 to n.


  • Find all squares with a number of factors which have a remainder of 1, when dividing by 6.



    import numpy as np


    # brute force to find number of factors for each n
    def factors(n):
    result =
    i = 1
    # This will loop from 1 to int(sqrt(n))
    while i * i <= n:
    # Check if i divides x without leaving a remainder
    if n % i == 0:
    result.append(i)
    if n / i != i:
    result.append(n / i)
    i += 1
    # Return the list of factors of x
    return len(result)


    vect_factors = np.vectorize(factors)


    # avoid brute forcing all numbers
    def f(n):
    # create an array of 1 to n + 1
    # find all perfect squares in that range
    dice = np.arange(1, n + 1)[(np.mod(np.sqrt(np.arange(1, n + 1)), 1) == 0)]
    # find all squares which have n-factors, which
    # when divided by 6 have a remainder of 1.
    dice = dice[np.mod(vect_factors(dice), 6) == 1]
    return len(dice)



Worth noting - on my machine, I'm unable to run larger than 10^10. While solving this would be ideal, I feel that what I've learned (and determined how to apply) in the process is enough for me.





UPDATE 11/13/2018



I'm continuing to spend a small bit of time trying to optimize this to get it processing more quickly. Here's the updated code base. This evaluates f(10**10) in 1 min and 17 seconds.



import time
from datetime import timedelta
import numpy as np
import math

from itertools import chain, cycle, accumulate


def find_squares(n):
return np.array([n ** 2 for n in np.arange(1, highest = math.sqrt(n) + 1)])

# brute force to find number of factors for each n
def find_factors(n):
def prime_powers(n):
# c goes through 2, 3, 5, then the infinite (6n+1, 6n+5) series
for c in accumulate(chain([2, 1, 2], cycle([2, 4]))):
if c * c > n: break
if n % c: continue
d, p = (), c
while not n % c:
n, p, d = n // c, p * c, d + (p,)
yield (d)
if n > 1: yield ((n,))

r = [1]
for e in prime_powers(n):
r += [a * b for a in r for b in e]
return len(r)


vect_factors = np.vectorize(find_factors)


# avoid brute forcing all numbers
def f(n):
# create an array of 1 to n + 1
# find all perfect squares in that range
start = time.time()
dice = find_squares(n)
# find all squares which have n-factors, which
# when divided by 6 have a remainder of 1.
dice = dice[np.mod(vect_factors(dice), 6) == 1]
diff = (timedelta(seconds=int(time.time() - start))).__str__()
print("{n} has {remain} dice with a value of 1. Computed in {diff}.".format(n=n, remain=len(dice), diff=diff))









share|improve this question















I'm working on solve the below problem from Project Euler, which in short deals with iterating over 'n' dice and updating their values.




A Long Row of Dice - project Euler problem #641



Consider a row of n dice all showing 1.



First turn every second die,(2,4,6,…), so that the number showing is increased by 1. Then turn every third die. The sixth die will now show a 3. Then turn every fourth die and so on until every nth die (only the last die) is turned. If the die to be turned is showing a 6 then it is changed to show a 1.



Let f(n) be the number of dice that are showing a 1 when the process finishes. You are given f(100)=2 and f(10^8)=69.



Find f(10^36).




I've written the below code in Python using numpy, but can't exactly figure out what I'm doing wrong to my function output to match the output above. Right now f(100) returns 1 (should be 2); even f(1000) returns 1.



import numpy as np

def f(n):
# establish dice and the value sets for the dice
dice = np.arange(1, n + 1)
dice_values = np.ones(len(dice))
turns = range(2, len(dice) + 1)
print("{a} dice, {b} values, {c} runs to process".format(a=len(dice), b=len(dice_values), c=len(turns)))

# iterate and update the values of each die
# in our array of dice
for turn in turns:
# if die to be processed is 6, update to 1
dice_values[(dice_values == 6) & (dice % turn == 0)] = 1

# update dice_values to if the die's index has no remainder
# from the turn we're processing.
dice_values += dice % turn == 0

# output status
print('Processed every {0} dice'.format(turn))
print('{0}nn'.format(dice_values))
return "f({n}) = {x}".format(n=n, x=len(np.where(dice_values == 1)))




UPDATE 11/12/18



@Prune's guidance has been extremely helpful. My methodology is now as follows:




  • Find all the squares from 1 to n.


  • Find all squares with a number of factors which have a remainder of 1, when dividing by 6.



    import numpy as np


    # brute force to find number of factors for each n
    def factors(n):
    result =
    i = 1
    # This will loop from 1 to int(sqrt(n))
    while i * i <= n:
    # Check if i divides x without leaving a remainder
    if n % i == 0:
    result.append(i)
    if n / i != i:
    result.append(n / i)
    i += 1
    # Return the list of factors of x
    return len(result)


    vect_factors = np.vectorize(factors)


    # avoid brute forcing all numbers
    def f(n):
    # create an array of 1 to n + 1
    # find all perfect squares in that range
    dice = np.arange(1, n + 1)[(np.mod(np.sqrt(np.arange(1, n + 1)), 1) == 0)]
    # find all squares which have n-factors, which
    # when divided by 6 have a remainder of 1.
    dice = dice[np.mod(vect_factors(dice), 6) == 1]
    return len(dice)



Worth noting - on my machine, I'm unable to run larger than 10^10. While solving this would be ideal, I feel that what I've learned (and determined how to apply) in the process is enough for me.





UPDATE 11/13/2018



I'm continuing to spend a small bit of time trying to optimize this to get it processing more quickly. Here's the updated code base. This evaluates f(10**10) in 1 min and 17 seconds.



import time
from datetime import timedelta
import numpy as np
import math

from itertools import chain, cycle, accumulate


def find_squares(n):
return np.array([n ** 2 for n in np.arange(1, highest = math.sqrt(n) + 1)])

# brute force to find number of factors for each n
def find_factors(n):
def prime_powers(n):
# c goes through 2, 3, 5, then the infinite (6n+1, 6n+5) series
for c in accumulate(chain([2, 1, 2], cycle([2, 4]))):
if c * c > n: break
if n % c: continue
d, p = (), c
while not n % c:
n, p, d = n // c, p * c, d + (p,)
yield (d)
if n > 1: yield ((n,))

r = [1]
for e in prime_powers(n):
r += [a * b for a in r for b in e]
return len(r)


vect_factors = np.vectorize(find_factors)


# avoid brute forcing all numbers
def f(n):
# create an array of 1 to n + 1
# find all perfect squares in that range
start = time.time()
dice = find_squares(n)
# find all squares which have n-factors, which
# when divided by 6 have a remainder of 1.
dice = dice[np.mod(vect_factors(dice), 6) == 1]
diff = (timedelta(seconds=int(time.time() - start))).__str__()
print("{n} has {remain} dice with a value of 1. Computed in {diff}.".format(n=n, remain=len(dice), diff=diff))






python numpy






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 at 16:58

























asked Nov 9 at 21:30









rs311

1359




1359








  • 2




    If your dice shows a 6 and has to be turned, you turn it first to 1, then again to 2. You'd rather add 1, then turn the 7 to 1, or use a modulo. Anyway, bruteforcing it won't help for f(10^36), you will have to do some maths...
    – Thierry Lathuille
    Nov 9 at 21:52










  • When you get to a resolution, please remember to up-vote useful things and accept your favourite answer (even if you have to write it yourself), so Stack Overflow can properly archive the question.
    – Prune
    Nov 12 at 18:43










  • Worth noting, on my machine the code from UPDATE 11/12/18 performs fairly well on 10^8, but begins breaking down at 10^9. f(10**8) -> 100000000 has 69 dice with a value of 1. Computed in 0:00:21. f(10**9) -> 1000000000 has 124 dice with a value of 1. Computed in 0:05:06. @Prune thanks for the help!
    – rs311
    Nov 12 at 22:25
















  • 2




    If your dice shows a 6 and has to be turned, you turn it first to 1, then again to 2. You'd rather add 1, then turn the 7 to 1, or use a modulo. Anyway, bruteforcing it won't help for f(10^36), you will have to do some maths...
    – Thierry Lathuille
    Nov 9 at 21:52










  • When you get to a resolution, please remember to up-vote useful things and accept your favourite answer (even if you have to write it yourself), so Stack Overflow can properly archive the question.
    – Prune
    Nov 12 at 18:43










  • Worth noting, on my machine the code from UPDATE 11/12/18 performs fairly well on 10^8, but begins breaking down at 10^9. f(10**8) -> 100000000 has 69 dice with a value of 1. Computed in 0:00:21. f(10**9) -> 1000000000 has 124 dice with a value of 1. Computed in 0:05:06. @Prune thanks for the help!
    – rs311
    Nov 12 at 22:25










2




2




If your dice shows a 6 and has to be turned, you turn it first to 1, then again to 2. You'd rather add 1, then turn the 7 to 1, or use a modulo. Anyway, bruteforcing it won't help for f(10^36), you will have to do some maths...
– Thierry Lathuille
Nov 9 at 21:52




If your dice shows a 6 and has to be turned, you turn it first to 1, then again to 2. You'd rather add 1, then turn the 7 to 1, or use a modulo. Anyway, bruteforcing it won't help for f(10^36), you will have to do some maths...
– Thierry Lathuille
Nov 9 at 21:52












When you get to a resolution, please remember to up-vote useful things and accept your favourite answer (even if you have to write it yourself), so Stack Overflow can properly archive the question.
– Prune
Nov 12 at 18:43




When you get to a resolution, please remember to up-vote useful things and accept your favourite answer (even if you have to write it yourself), so Stack Overflow can properly archive the question.
– Prune
Nov 12 at 18:43












Worth noting, on my machine the code from UPDATE 11/12/18 performs fairly well on 10^8, but begins breaking down at 10^9. f(10**8) -> 100000000 has 69 dice with a value of 1. Computed in 0:00:21. f(10**9) -> 1000000000 has 124 dice with a value of 1. Computed in 0:05:06. @Prune thanks for the help!
– rs311
Nov 12 at 22:25






Worth noting, on my machine the code from UPDATE 11/12/18 performs fairly well on 10^8, but begins breaking down at 10^9. f(10**8) -> 100000000 has 69 dice with a value of 1. Computed in 0:00:21. f(10**9) -> 1000000000 has 124 dice with a value of 1. Computed in 0:05:06. @Prune thanks for the help!
– rs311
Nov 12 at 22:25














2 Answers
2






active

oldest

votes

















up vote
4
down vote



accepted










I'm raising an x/y issue. Fixing your 6 => 1 flip will correct your code, but it will not solve the presented problem in reasonable time. To find f(10^36), you're processing 10^36 dice 10^36 times each, even if it's merely a divisibility check in the filter. That's a total of 10^72 checks. I don't know what hardware you have, but even my multi-core monster doesn't loop 10^72 times soon enough for comfort.



Instead, you need to figure out the underlying problem and try to generate a count for integers that fit the description.



The dice are merely a device to count something in mod 6. We're counting divisors of a number, including 1 and the number itself. This the (in)famous divisor function.



The problem at hand doesn't ask us to find σ0(n) for all numbers; it wants us to count how many integers have σ0(n) = 1 (mod 6). These are numbers with 1, 7, 13, 19, ... divisors.



First of all, note that this is an odd number. The only integers with an odd number of divisors are perfect squares. Look at the divisor function; how can we tell whether the square of a number will have the desired quantity of factors, 1 (mod 6)?



Does that get you moving?





WEEKEND UPDATE



My code to step through 10^18 candidates is still too slow to finish in this calendar year. It did well up to about 10^7 and then bogged down in the ON(log N) checking steps.



However, there are many more restrictions I've noted in my tracing output.
The main one is in characterizing what combinations of prime powers result in a solution. If we reduce each power mod 3, we have the following:





  • 0 values do not affect validity of the result.


  • 1 values make the number invalid.


  • 2 values must be paired.


Also, these conditions are both necessary and sufficient to declare a given number as a solution. Therefore, it's possible to generate the desired solutions without bothering to step through the squares of all integers <= 10^18.



Among other things, we will need only primes up to 10^9: a solution's square root will need at least 2 of any prime factor.



I hope that's enough hints for now ... you'll need to construct an algorithm to generate certain restricted composite combinations with a given upper limit for the product.






share|improve this answer























  • thanks for your help and guidance. The brute force approach was really focused on the smaller functions. Your background related to the divisor function will be really helpful for solving the larger problems f(10^8) and f(10^36).
    – rs311
    Nov 12 at 14:33










  • [headslap] I inverted the problem, because it was interesting. I sent mine off to find all integers <= 10^36 such that f(n) == 2. That's what's taking so long ...
    – Prune
    Nov 12 at 23:04




















up vote
1
down vote













As mentioned by Thierry in the comments, you are looping back to 2 when you flip dice at a 6. I'd suggest just changing dice_values[(dice_values == 6) & (dice % turn == 0)] = 1 to equal 0.



You also have an issue with return "f({n}) = {x}".format(n=n, x=len(np.where(dice_values == 1))) that I'd fix by replacing x=len(np.where(dice_values == 1)) with x=np.count_nonzero(dice_values == 1)



Doing both these changes gave me an output of f(100)=2






share|improve this answer





















  • Thanks, @BaronVonRhett. These were very helpful comments related to solving the f(100) and f(1000) questions.
    – rs311
    Nov 12 at 14:29











Your Answer






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: "1"
};
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',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
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
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53233498%2fproject-euler-641-python-3-6-numpy%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








up vote
4
down vote



accepted










I'm raising an x/y issue. Fixing your 6 => 1 flip will correct your code, but it will not solve the presented problem in reasonable time. To find f(10^36), you're processing 10^36 dice 10^36 times each, even if it's merely a divisibility check in the filter. That's a total of 10^72 checks. I don't know what hardware you have, but even my multi-core monster doesn't loop 10^72 times soon enough for comfort.



Instead, you need to figure out the underlying problem and try to generate a count for integers that fit the description.



The dice are merely a device to count something in mod 6. We're counting divisors of a number, including 1 and the number itself. This the (in)famous divisor function.



The problem at hand doesn't ask us to find σ0(n) for all numbers; it wants us to count how many integers have σ0(n) = 1 (mod 6). These are numbers with 1, 7, 13, 19, ... divisors.



First of all, note that this is an odd number. The only integers with an odd number of divisors are perfect squares. Look at the divisor function; how can we tell whether the square of a number will have the desired quantity of factors, 1 (mod 6)?



Does that get you moving?





WEEKEND UPDATE



My code to step through 10^18 candidates is still too slow to finish in this calendar year. It did well up to about 10^7 and then bogged down in the ON(log N) checking steps.



However, there are many more restrictions I've noted in my tracing output.
The main one is in characterizing what combinations of prime powers result in a solution. If we reduce each power mod 3, we have the following:





  • 0 values do not affect validity of the result.


  • 1 values make the number invalid.


  • 2 values must be paired.


Also, these conditions are both necessary and sufficient to declare a given number as a solution. Therefore, it's possible to generate the desired solutions without bothering to step through the squares of all integers <= 10^18.



Among other things, we will need only primes up to 10^9: a solution's square root will need at least 2 of any prime factor.



I hope that's enough hints for now ... you'll need to construct an algorithm to generate certain restricted composite combinations with a given upper limit for the product.






share|improve this answer























  • thanks for your help and guidance. The brute force approach was really focused on the smaller functions. Your background related to the divisor function will be really helpful for solving the larger problems f(10^8) and f(10^36).
    – rs311
    Nov 12 at 14:33










  • [headslap] I inverted the problem, because it was interesting. I sent mine off to find all integers <= 10^36 such that f(n) == 2. That's what's taking so long ...
    – Prune
    Nov 12 at 23:04

















up vote
4
down vote



accepted










I'm raising an x/y issue. Fixing your 6 => 1 flip will correct your code, but it will not solve the presented problem in reasonable time. To find f(10^36), you're processing 10^36 dice 10^36 times each, even if it's merely a divisibility check in the filter. That's a total of 10^72 checks. I don't know what hardware you have, but even my multi-core monster doesn't loop 10^72 times soon enough for comfort.



Instead, you need to figure out the underlying problem and try to generate a count for integers that fit the description.



The dice are merely a device to count something in mod 6. We're counting divisors of a number, including 1 and the number itself. This the (in)famous divisor function.



The problem at hand doesn't ask us to find σ0(n) for all numbers; it wants us to count how many integers have σ0(n) = 1 (mod 6). These are numbers with 1, 7, 13, 19, ... divisors.



First of all, note that this is an odd number. The only integers with an odd number of divisors are perfect squares. Look at the divisor function; how can we tell whether the square of a number will have the desired quantity of factors, 1 (mod 6)?



Does that get you moving?





WEEKEND UPDATE



My code to step through 10^18 candidates is still too slow to finish in this calendar year. It did well up to about 10^7 and then bogged down in the ON(log N) checking steps.



However, there are many more restrictions I've noted in my tracing output.
The main one is in characterizing what combinations of prime powers result in a solution. If we reduce each power mod 3, we have the following:





  • 0 values do not affect validity of the result.


  • 1 values make the number invalid.


  • 2 values must be paired.


Also, these conditions are both necessary and sufficient to declare a given number as a solution. Therefore, it's possible to generate the desired solutions without bothering to step through the squares of all integers <= 10^18.



Among other things, we will need only primes up to 10^9: a solution's square root will need at least 2 of any prime factor.



I hope that's enough hints for now ... you'll need to construct an algorithm to generate certain restricted composite combinations with a given upper limit for the product.






share|improve this answer























  • thanks for your help and guidance. The brute force approach was really focused on the smaller functions. Your background related to the divisor function will be really helpful for solving the larger problems f(10^8) and f(10^36).
    – rs311
    Nov 12 at 14:33










  • [headslap] I inverted the problem, because it was interesting. I sent mine off to find all integers <= 10^36 such that f(n) == 2. That's what's taking so long ...
    – Prune
    Nov 12 at 23:04















up vote
4
down vote



accepted







up vote
4
down vote



accepted






I'm raising an x/y issue. Fixing your 6 => 1 flip will correct your code, but it will not solve the presented problem in reasonable time. To find f(10^36), you're processing 10^36 dice 10^36 times each, even if it's merely a divisibility check in the filter. That's a total of 10^72 checks. I don't know what hardware you have, but even my multi-core monster doesn't loop 10^72 times soon enough for comfort.



Instead, you need to figure out the underlying problem and try to generate a count for integers that fit the description.



The dice are merely a device to count something in mod 6. We're counting divisors of a number, including 1 and the number itself. This the (in)famous divisor function.



The problem at hand doesn't ask us to find σ0(n) for all numbers; it wants us to count how many integers have σ0(n) = 1 (mod 6). These are numbers with 1, 7, 13, 19, ... divisors.



First of all, note that this is an odd number. The only integers with an odd number of divisors are perfect squares. Look at the divisor function; how can we tell whether the square of a number will have the desired quantity of factors, 1 (mod 6)?



Does that get you moving?





WEEKEND UPDATE



My code to step through 10^18 candidates is still too slow to finish in this calendar year. It did well up to about 10^7 and then bogged down in the ON(log N) checking steps.



However, there are many more restrictions I've noted in my tracing output.
The main one is in characterizing what combinations of prime powers result in a solution. If we reduce each power mod 3, we have the following:





  • 0 values do not affect validity of the result.


  • 1 values make the number invalid.


  • 2 values must be paired.


Also, these conditions are both necessary and sufficient to declare a given number as a solution. Therefore, it's possible to generate the desired solutions without bothering to step through the squares of all integers <= 10^18.



Among other things, we will need only primes up to 10^9: a solution's square root will need at least 2 of any prime factor.



I hope that's enough hints for now ... you'll need to construct an algorithm to generate certain restricted composite combinations with a given upper limit for the product.






share|improve this answer














I'm raising an x/y issue. Fixing your 6 => 1 flip will correct your code, but it will not solve the presented problem in reasonable time. To find f(10^36), you're processing 10^36 dice 10^36 times each, even if it's merely a divisibility check in the filter. That's a total of 10^72 checks. I don't know what hardware you have, but even my multi-core monster doesn't loop 10^72 times soon enough for comfort.



Instead, you need to figure out the underlying problem and try to generate a count for integers that fit the description.



The dice are merely a device to count something in mod 6. We're counting divisors of a number, including 1 and the number itself. This the (in)famous divisor function.



The problem at hand doesn't ask us to find σ0(n) for all numbers; it wants us to count how many integers have σ0(n) = 1 (mod 6). These are numbers with 1, 7, 13, 19, ... divisors.



First of all, note that this is an odd number. The only integers with an odd number of divisors are perfect squares. Look at the divisor function; how can we tell whether the square of a number will have the desired quantity of factors, 1 (mod 6)?



Does that get you moving?





WEEKEND UPDATE



My code to step through 10^18 candidates is still too slow to finish in this calendar year. It did well up to about 10^7 and then bogged down in the ON(log N) checking steps.



However, there are many more restrictions I've noted in my tracing output.
The main one is in characterizing what combinations of prime powers result in a solution. If we reduce each power mod 3, we have the following:





  • 0 values do not affect validity of the result.


  • 1 values make the number invalid.


  • 2 values must be paired.


Also, these conditions are both necessary and sufficient to declare a given number as a solution. Therefore, it's possible to generate the desired solutions without bothering to step through the squares of all integers <= 10^18.



Among other things, we will need only primes up to 10^9: a solution's square root will need at least 2 of any prime factor.



I hope that's enough hints for now ... you'll need to construct an algorithm to generate certain restricted composite combinations with a given upper limit for the product.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 12 at 18:57

























answered Nov 9 at 23:28









Prune

41.7k133454




41.7k133454












  • thanks for your help and guidance. The brute force approach was really focused on the smaller functions. Your background related to the divisor function will be really helpful for solving the larger problems f(10^8) and f(10^36).
    – rs311
    Nov 12 at 14:33










  • [headslap] I inverted the problem, because it was interesting. I sent mine off to find all integers <= 10^36 such that f(n) == 2. That's what's taking so long ...
    – Prune
    Nov 12 at 23:04




















  • thanks for your help and guidance. The brute force approach was really focused on the smaller functions. Your background related to the divisor function will be really helpful for solving the larger problems f(10^8) and f(10^36).
    – rs311
    Nov 12 at 14:33










  • [headslap] I inverted the problem, because it was interesting. I sent mine off to find all integers <= 10^36 such that f(n) == 2. That's what's taking so long ...
    – Prune
    Nov 12 at 23:04


















thanks for your help and guidance. The brute force approach was really focused on the smaller functions. Your background related to the divisor function will be really helpful for solving the larger problems f(10^8) and f(10^36).
– rs311
Nov 12 at 14:33




thanks for your help and guidance. The brute force approach was really focused on the smaller functions. Your background related to the divisor function will be really helpful for solving the larger problems f(10^8) and f(10^36).
– rs311
Nov 12 at 14:33












[headslap] I inverted the problem, because it was interesting. I sent mine off to find all integers <= 10^36 such that f(n) == 2. That's what's taking so long ...
– Prune
Nov 12 at 23:04






[headslap] I inverted the problem, because it was interesting. I sent mine off to find all integers <= 10^36 such that f(n) == 2. That's what's taking so long ...
– Prune
Nov 12 at 23:04














up vote
1
down vote













As mentioned by Thierry in the comments, you are looping back to 2 when you flip dice at a 6. I'd suggest just changing dice_values[(dice_values == 6) & (dice % turn == 0)] = 1 to equal 0.



You also have an issue with return "f({n}) = {x}".format(n=n, x=len(np.where(dice_values == 1))) that I'd fix by replacing x=len(np.where(dice_values == 1)) with x=np.count_nonzero(dice_values == 1)



Doing both these changes gave me an output of f(100)=2






share|improve this answer





















  • Thanks, @BaronVonRhett. These were very helpful comments related to solving the f(100) and f(1000) questions.
    – rs311
    Nov 12 at 14:29















up vote
1
down vote













As mentioned by Thierry in the comments, you are looping back to 2 when you flip dice at a 6. I'd suggest just changing dice_values[(dice_values == 6) & (dice % turn == 0)] = 1 to equal 0.



You also have an issue with return "f({n}) = {x}".format(n=n, x=len(np.where(dice_values == 1))) that I'd fix by replacing x=len(np.where(dice_values == 1)) with x=np.count_nonzero(dice_values == 1)



Doing both these changes gave me an output of f(100)=2






share|improve this answer





















  • Thanks, @BaronVonRhett. These were very helpful comments related to solving the f(100) and f(1000) questions.
    – rs311
    Nov 12 at 14:29













up vote
1
down vote










up vote
1
down vote









As mentioned by Thierry in the comments, you are looping back to 2 when you flip dice at a 6. I'd suggest just changing dice_values[(dice_values == 6) & (dice % turn == 0)] = 1 to equal 0.



You also have an issue with return "f({n}) = {x}".format(n=n, x=len(np.where(dice_values == 1))) that I'd fix by replacing x=len(np.where(dice_values == 1)) with x=np.count_nonzero(dice_values == 1)



Doing both these changes gave me an output of f(100)=2






share|improve this answer












As mentioned by Thierry in the comments, you are looping back to 2 when you flip dice at a 6. I'd suggest just changing dice_values[(dice_values == 6) & (dice % turn == 0)] = 1 to equal 0.



You also have an issue with return "f({n}) = {x}".format(n=n, x=len(np.where(dice_values == 1))) that I'd fix by replacing x=len(np.where(dice_values == 1)) with x=np.count_nonzero(dice_values == 1)



Doing both these changes gave me an output of f(100)=2







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 9 at 22:28









BaronVonRhett

134




134












  • Thanks, @BaronVonRhett. These were very helpful comments related to solving the f(100) and f(1000) questions.
    – rs311
    Nov 12 at 14:29


















  • Thanks, @BaronVonRhett. These were very helpful comments related to solving the f(100) and f(1000) questions.
    – rs311
    Nov 12 at 14:29
















Thanks, @BaronVonRhett. These were very helpful comments related to solving the f(100) and f(1000) questions.
– rs311
Nov 12 at 14:29




Thanks, @BaronVonRhett. These were very helpful comments related to solving the f(100) and f(1000) questions.
– rs311
Nov 12 at 14:29


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • 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.


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





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • 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.


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%2fstackoverflow.com%2fquestions%2f53233498%2fproject-euler-641-python-3-6-numpy%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

Schultheiß

Verwaltungsgliederung Dänemarks

Liste der Kulturdenkmale in Wilsdruff