Euler 0012
The Problem:
FindWhat is the greatest productvalue of 4the adjacentfirst numberstriangle innumber to have over five hundred divisors?
Considerations:
We don't actually need to compute all of the griddivisors (of a number, since the number of divisors can be calculated by knowing the number of prime factors.
12, for example, has prime factors 2(2 of these) and 3. It has a total of 6 divisors, which can be foundcalculated onby taking the PEquantity website)of each prime factor and adding 1, 2 for 2 becomes 3 and 1 for 3 becomes 2... ThisOk, maybe that's an obtuse way of explaining it... If you want a good explanation of it, you can befind up,it down,here: left, right, or diagonal.https://mathschallenge.net/library/number/number_of_divisors
Considerations:
We don't need to check left ever. In the last 3 columns we don't check right, either.We don't need to check up ever. In the last 3 rows we don't check down.We don't need to check up diagonals. We will check both left and right diagonals, and ignore the relevant diagonals when we are in the first or last 3 columns. We don't need to check diagonals in the last 3 rows.
The Approach:
StartingWe fromare 0,0going beingto use the topmostsame leftmostprime cornerfactors finder that we have before, but instead of the grid, we canare keepgoing iteratingto throughmultiple andby checkinga everyrunning case,divisors remembering the considerations above.count.
The Code:
import numpymath
from#This enumis importa Enummodification classof Direction(Enum)the prime factor finder
def calculate_divisors(number):
#notupper_limit necessary= number
current_upper_limit = upper_limit
sqrt_limit = math.sqrt(upper_limit)
current_divisors = 1
#we are going to thehardcode solution,2 butand helps3 mefor aslooping asake
humanif visualizeupper_limit where% the2 solution== is0:
at
DOWNcurrent_div = "DOWN"1
RIGHTwhile current_upper_limit % 2 == 0:
current_upper_limit = "RIGHT"current_upper_limit/2
LEFT_DIAGcurrent_div += 1
current_divisors *= current_div
if upper_limit % 3 == 0:
current_div = "LEFT_DIAG"1
RIGHT_DIAGwhile current_upper_limit % 3 == 0:
current_upper_limit = "RIGHT_DIAG"current_upper_limit/3
best_indexcurrent_div += 1
current_divisors *= current_div
current = [0,0]6
best_dirwhile current < sqrt_limit:
#print(prime_factors, current_upper_limit)
if current_upper_limit % (current - 1) == 0:
current_div = Direction.DOWN1
best_productwhile current_upper_limit % (current - 1) == 0:
current_upper_limit = 0current_upper_limit/(current-1)
lengthcurrent_div += 1
current_divisors *= current_div
if current_upper_limit % (current + 1) == 0:
current_div = 41
gridwhile current_upper_limit % (current + 1) == 0:
current_upper_limit = numpy.genfromtxt("numbers",current_upper_limit/(current+1)
delimiter="current_div ")+= #using1
numpycurrent_divisors to*= readcurrent_div
incurrent the+= file6
return current_divisors
bailout = 100000 #keep checking up to a gridbailout fornumber
ustriangle = 1
for i in range(len(grid))2,bailout):
#gotriangle through+= every row in the grid
for j in range(len(grid[i])): #go through every column in the grid
#print(i,j)
#check righti
if j < len(grid)-(length-1):
current_prod = 1
for k in range(length):
current_prod *= grid[i,j+k]
if current_prodcalculate_divisors(triangle) >= best_product:500:
best_index = [i,j]
best_dir = Direction.RIGHT
best_product = current_prod
#check down
if i < len(grid)-(length-1):
current_prod = 1
for k in range(length):
current_prod *= grid[i+k,j]
if current_prod >= best_product:
best_index = [i,j]
best_dir = Direction.DOWN
best_product = current_prod
#check down right
if i < len(grid)-(length-1) and j < len(grid)-(length-1):
current_prod = 1
for k in range(length):
current_prod *= grid[i+k,j+k]
if current_prod >= best_product:
best_index = [i,j]
best_dir = Direction.RIGHT_DIAG
best_product = current_prod
#check down left
if i < len(grid)-(length-1) and j > (length-1):
current_prod = 1
for k in range(length):
current_prod *= grid[i+k,j-k]
if current_prod >= best_product:
best_index = [i,j]
best_dir = Direction.LEFT_DIAG
best_product = current_prodbreak
print(best_index,i, best_dir, best_product) #prints out the best position, the direction it points, and the producttriangle)