patternpythonMinor
Central Delannoy numbers
Viewed 0 times
centralnumbersdelannoy
Problem
I am solving this problem on SPOJ Upper Right King (Hard):
There is a king in the lower left corner of the \$ n \times n \$ chess board. The king can move one step right, one step up or one step up-right. How many ways are there for him to reach the upper right corner of the board? Give the answer modulo 1000003.
The numbers to be output are the central Delannoy numbers.
I've written a solution in Python with a time complexity of \$ O(n(\log m)^2) \$. But it's showing "time limit exceeded". Can anyone help me out with this?
How can I reduce the complexity of this problem in order to have it accepted?
There is a king in the lower left corner of the \$ n \times n \$ chess board. The king can move one step right, one step up or one step up-right. How many ways are there for him to reach the upper right corner of the board? Give the answer modulo 1000003.
The numbers to be output are the central Delannoy numbers.
I've written a solution in Python with a time complexity of \$ O(n(\log m)^2) \$. But it's showing "time limit exceeded". Can anyone help me out with this?
import math
MAX = 10000002
MOD = 1000003
# Extended euclidean algorithm for modular inverse
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
return 0
else:
return x % m
t = raw_input()
t = long(t)
fact = []
for i in range(0,MAX):
fact.append(0)
fact[0]=1
fact[1]=1
for i in range(2,MAX):
fact[i] = (i%MOD * fact[i-1]%MOD)%MOD
while t:
n = raw_input()
n = long(n)
n = n-1
Sum = 1
prod = ((n+1)%MOD * (n)%MOD)%MOD
increment = n+1
decrement = n
Sum = (Sum%MOD + prod%MOD)%MOD
for k in range(0,n-1):
temp_prod = (prod%MOD * (increment+1)%MOD * (decrement-1)%MOD)%MOD
prod = temp_prod
fct = fact[k+2]
fat2 = (fct%MOD * fct%MOD)%MOD
# print fat2,modinv(fat2,MOD)
result = (temp_prod%MOD * modinv(fat2,MOD))%MOD
Sum = (Sum%MOD + result%MOD)%MOD
increment = increment + 1
decrement = decrement - 1
print "%ld" %(Sum)
t = t-1How can I reduce the complexity of this problem in order to have it accepted?
Solution
Flatten your method body
can be re-written as:
because returning halts the function.
Use in-line 'ternary' to reduce verbosity
should become
Say something meaningful when asking for input
The user sees nothing, only an hanging interpreter.
Use a main function
Convert directly (minor)
Do not waste lines:
should become
n = long(raw_input()) # <- also add a meaningful prompt
Follow naming conventions (minor)
You follow the naming conventions pretty well, just one imprecision:
should be:
Use proper spacing (minor)
For example this line:
is hard to read because all the symbols are squashed together.
Modularize more (important)
You defined two functions, that is very good, but you could do more to reduce the 35 lines of top level imperative code that is too much.
Usually each function (including
Use doctests to for automatic testing
In Math code, automatically testing your functions each time you run the programme can be invaluable, just use something like:
and the code will be tested automatically.
Tell why
I can see many calculations in your code, but why? Following which algorithm, please write this inside the docstrings of your functions.
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)can be re-written as:
def egcd(a, b):
if a == 0:
return (b, 0, 1)
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)because returning halts the function.
Use in-line 'ternary' to reduce verbosity
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
return 0
else:
return x % mshould become
def modinv(a, m):
g, x, y = egcd(a, m)
return 0 if g != 1 else x % mSay something meaningful when asking for input
t = raw_input()The user sees nothing, only an hanging interpreter.
Use a main function
- Python code runs faster in functions
- You can use an if name ... block to avoid execution when the module is imported.
Convert directly (minor)
Do not waste lines:
n = raw_input()
n = long(n)should become
n = long(raw_input()) # <- also add a meaningful prompt
Follow naming conventions (minor)
You follow the naming conventions pretty well, just one imprecision:
Sum = 1should be:
sum = 1Use proper spacing (minor)
For example this line:
prod = ((n+1)%MOD * (n)%MOD)%MODis hard to read because all the symbols are squashed together.
Modularize more (important)
You defined two functions, that is very good, but you could do more to reduce the 35 lines of top level imperative code that is too much.
Usually each function (including
main) should be no more than 10-15 lines of code.Use doctests to for automatic testing
In Math code, automatically testing your functions each time you run the programme can be invaluable, just use something like:
import doctest
def egcd(a, b):
"""
Meaningful description here...
>>> egcd(4132, 434)
(2, -48, 457)
"""
if a == 0:
return (b, 0, 1)
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
doctest.testmod()and the code will be tested automatically.
Tell why
I can see many calculations in your code, but why? Following which algorithm, please write this inside the docstrings of your functions.
Code Snippets
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)def egcd(a, b):
if a == 0:
return (b, 0, 1)
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
return 0
else:
return x % mdef modinv(a, m):
g, x, y = egcd(a, m)
return 0 if g != 1 else x % mt = raw_input()Context
StackExchange Code Review Q#33575, answer score: 2
Revisions (0)
No revisions yet.