patternpythonMinor
Project Euler 28 - Number Spiral Diagonals
Viewed 0 times
numberdiagonalsprojecteulerspiral
Problem
Project Euler problem 28
Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:
$$\begin{array}{rrrrr}
\color{red}{21} &22 &23 &24 &\color{red}{25}\\
20 & \color{red}{7} & 8 & \color{red}{9} &10\\
19 & 6 & \color{red}{1} & 2 &11\\
18 & \color{red}{5} & 4 & \color{red}{3} &12\\
\color{red}{17} &16 &15 &14 &\color{red}{13}\\
\end{array}$$
It can be verified that the sum of the numbers on the diagonals is 101.
What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way?
I realized that the spiral was essentially an arithmetic sequence, so I based my code off of that.
Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:
$$\begin{array}{rrrrr}
\color{red}{21} &22 &23 &24 &\color{red}{25}\\
20 & \color{red}{7} & 8 & \color{red}{9} &10\\
19 & 6 & \color{red}{1} & 2 &11\\
18 & \color{red}{5} & 4 & \color{red}{3} &12\\
\color{red}{17} &16 &15 &14 &\color{red}{13}\\
\end{array}$$
It can be verified that the sum of the numbers on the diagonals is 101.
What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way?
I realized that the spiral was essentially an arithmetic sequence, so I based my code off of that.
from timeit import default_timer as timer
start = timer()
def spiral_diag_sum(n):
if n ms
print "Found %d in %r ms." % (ans, elapsed_time)Solution
from timeit import default_timer as timer
start = timer()This line of code belongs with the code at the end of the program that times the call to
spiral_diag_sum.def spiral_diag_sum(n):It's always a good idea to add a docstring. Several of the later Project Euler problems rely on finding a solution to earlier ones (though perhaps not this one), so you'll find yourself building up a library of useful code to reuse, in which case a good docstring makes it much easier to import.
if n < 1: return None
elif n == 1: return 1
elif n % 2 == 0: return None
else:Checking that your arguments are sane is good. However, here you've got (in sequence) an error condition, a successful return, an error condition and (following the
else) the main body of the function. It's better to separate the error conditions and handle them first.You're also returning
None as the error value, but you're not checking for that value after you call spiral_diag_sum at the end of the program. Add code to check that, or better yet, raise an exception here indicating the error. Since both the n 2. The values of the other three corners can be derived from that value. The same formula also works for the central 1x1 square so you don't even need to have a special case for it.
ans = spiral_diag_sum(1001)
elapsed_time = (timer() - start) * 100 # s --> ms
print "Found %d in %r ms." % (ans, elapsed_time)
Following from some things I mentioned earlier: making this into a module that you can use in later problems, checking for a valid return value from spiral_diag_sum`, and keeping all the timing code together:if __name__ == "__main__": # Allows standalone use or as a library module.
start = timer() # This code moved from above.
ans = spiral_diag_sum(2)
elapsed_time = (timer() - start) * 100 # s --> ms
if ans: # Check for valid answer (or use try / except)
print "Found %d in %r ms." % (ans, elapsed_time)
else:
print "No answer returned"Code Snippets
from timeit import default_timer as timer
start = timer()def spiral_diag_sum(n):if n < 1: return None
elif n == 1: return 1
elif n % 2 == 0: return None
else:if n < 1 or n % 2 == 0:
raise ValueError("argument must be an odd-valued integer >= 1")if n == 1:
return 1Context
StackExchange Code Review Q#47056, answer score: 7
Revisions (0)
No revisions yet.