Insect combinatorics challenge
Below is the problem taken from Berkeley's Cs61A page here
Question 9: Insect Combinatorics*
Consider an insect in an M by N grid. The insect starts at the bottom left corner, (0, 0), and wants to end up at the top right corner, (M-1, N-1). The insect is only capable of moving right or up. Write a function paths that takes a grid length and width and returns the number of different paths the insect can take from the start to the goal. (There is a closed-form solution to this problem, but try to answer it procedurally using recursion.)
For example, the 2 by 2 grid has a total of two ways for the insect to move from the start to the goal. For the 3 by 3 grid, the insect has 6 diferent paths (only 3 are shown above).
def paths(m, n):
"""Return the number of paths from one corner of an
M by N grid to the opposite corner.
>>> paths(2, 2)
2
>>> paths(5, 7)
210
>>> paths(117, 1)
1
>>> paths(1, 157)
1
"""
"*** YOUR CODE HERE ***"
This solution is with the knowledge of 'higher order function' and 'recursion'. I've yet to learn data structures and algorithms (if required).
Idea: Started from the destination and found the possibilities. As per the skill level, the solution took 3 hours of my time. Please provide feedback on this.
def paths(m, n):
"""Return the number of paths from one corner of an
M by N grid to the opposite corner.
>>> paths(2, 2)
2
>>> paths(5, 7)
210
>>> paths(117, 1)
1
>>> paths(1, 157)
1
"""
count_paths = 0
def find_number_of_paths(x, y):
if x == 0 and y == 0:
nonlocal count_paths
count_paths += 1
return
if x > 0:
find_number_of_paths(x-1, y)
if y > 0:
find_number_of_paths(x, y-1)
find_number_of_paths(m-1, n-1)
return count_paths
- Can we avoid re-assignment operator on
count_paths
? - Can we avoid nested function definitions?
- Is there a name for above solution approach in algorithm world? Any better approach?
Note: As per this assignment, no usage of data model is recommended.
python python-3.x recursion homework combinatorics
add a comment |
Below is the problem taken from Berkeley's Cs61A page here
Question 9: Insect Combinatorics*
Consider an insect in an M by N grid. The insect starts at the bottom left corner, (0, 0), and wants to end up at the top right corner, (M-1, N-1). The insect is only capable of moving right or up. Write a function paths that takes a grid length and width and returns the number of different paths the insect can take from the start to the goal. (There is a closed-form solution to this problem, but try to answer it procedurally using recursion.)
For example, the 2 by 2 grid has a total of two ways for the insect to move from the start to the goal. For the 3 by 3 grid, the insect has 6 diferent paths (only 3 are shown above).
def paths(m, n):
"""Return the number of paths from one corner of an
M by N grid to the opposite corner.
>>> paths(2, 2)
2
>>> paths(5, 7)
210
>>> paths(117, 1)
1
>>> paths(1, 157)
1
"""
"*** YOUR CODE HERE ***"
This solution is with the knowledge of 'higher order function' and 'recursion'. I've yet to learn data structures and algorithms (if required).
Idea: Started from the destination and found the possibilities. As per the skill level, the solution took 3 hours of my time. Please provide feedback on this.
def paths(m, n):
"""Return the number of paths from one corner of an
M by N grid to the opposite corner.
>>> paths(2, 2)
2
>>> paths(5, 7)
210
>>> paths(117, 1)
1
>>> paths(1, 157)
1
"""
count_paths = 0
def find_number_of_paths(x, y):
if x == 0 and y == 0:
nonlocal count_paths
count_paths += 1
return
if x > 0:
find_number_of_paths(x-1, y)
if y > 0:
find_number_of_paths(x, y-1)
find_number_of_paths(m-1, n-1)
return count_paths
- Can we avoid re-assignment operator on
count_paths
? - Can we avoid nested function definitions?
- Is there a name for above solution approach in algorithm world? Any better approach?
Note: As per this assignment, no usage of data model is recommended.
python python-3.x recursion homework combinatorics
add a comment |
Below is the problem taken from Berkeley's Cs61A page here
Question 9: Insect Combinatorics*
Consider an insect in an M by N grid. The insect starts at the bottom left corner, (0, 0), and wants to end up at the top right corner, (M-1, N-1). The insect is only capable of moving right or up. Write a function paths that takes a grid length and width and returns the number of different paths the insect can take from the start to the goal. (There is a closed-form solution to this problem, but try to answer it procedurally using recursion.)
For example, the 2 by 2 grid has a total of two ways for the insect to move from the start to the goal. For the 3 by 3 grid, the insect has 6 diferent paths (only 3 are shown above).
def paths(m, n):
"""Return the number of paths from one corner of an
M by N grid to the opposite corner.
>>> paths(2, 2)
2
>>> paths(5, 7)
210
>>> paths(117, 1)
1
>>> paths(1, 157)
1
"""
"*** YOUR CODE HERE ***"
This solution is with the knowledge of 'higher order function' and 'recursion'. I've yet to learn data structures and algorithms (if required).
Idea: Started from the destination and found the possibilities. As per the skill level, the solution took 3 hours of my time. Please provide feedback on this.
def paths(m, n):
"""Return the number of paths from one corner of an
M by N grid to the opposite corner.
>>> paths(2, 2)
2
>>> paths(5, 7)
210
>>> paths(117, 1)
1
>>> paths(1, 157)
1
"""
count_paths = 0
def find_number_of_paths(x, y):
if x == 0 and y == 0:
nonlocal count_paths
count_paths += 1
return
if x > 0:
find_number_of_paths(x-1, y)
if y > 0:
find_number_of_paths(x, y-1)
find_number_of_paths(m-1, n-1)
return count_paths
- Can we avoid re-assignment operator on
count_paths
? - Can we avoid nested function definitions?
- Is there a name for above solution approach in algorithm world? Any better approach?
Note: As per this assignment, no usage of data model is recommended.
python python-3.x recursion homework combinatorics
Below is the problem taken from Berkeley's Cs61A page here
Question 9: Insect Combinatorics*
Consider an insect in an M by N grid. The insect starts at the bottom left corner, (0, 0), and wants to end up at the top right corner, (M-1, N-1). The insect is only capable of moving right or up. Write a function paths that takes a grid length and width and returns the number of different paths the insect can take from the start to the goal. (There is a closed-form solution to this problem, but try to answer it procedurally using recursion.)
For example, the 2 by 2 grid has a total of two ways for the insect to move from the start to the goal. For the 3 by 3 grid, the insect has 6 diferent paths (only 3 are shown above).
def paths(m, n):
"""Return the number of paths from one corner of an
M by N grid to the opposite corner.
>>> paths(2, 2)
2
>>> paths(5, 7)
210
>>> paths(117, 1)
1
>>> paths(1, 157)
1
"""
"*** YOUR CODE HERE ***"
This solution is with the knowledge of 'higher order function' and 'recursion'. I've yet to learn data structures and algorithms (if required).
Idea: Started from the destination and found the possibilities. As per the skill level, the solution took 3 hours of my time. Please provide feedback on this.
def paths(m, n):
"""Return the number of paths from one corner of an
M by N grid to the opposite corner.
>>> paths(2, 2)
2
>>> paths(5, 7)
210
>>> paths(117, 1)
1
>>> paths(1, 157)
1
"""
count_paths = 0
def find_number_of_paths(x, y):
if x == 0 and y == 0:
nonlocal count_paths
count_paths += 1
return
if x > 0:
find_number_of_paths(x-1, y)
if y > 0:
find_number_of_paths(x, y-1)
find_number_of_paths(m-1, n-1)
return count_paths
- Can we avoid re-assignment operator on
count_paths
? - Can we avoid nested function definitions?
- Is there a name for above solution approach in algorithm world? Any better approach?
Note: As per this assignment, no usage of data model is recommended.
python python-3.x recursion homework combinatorics
python python-3.x recursion homework combinatorics
edited Apr 2 '18 at 22:31
Grant Miller
2232416
2232416
asked Jun 30 '15 at 9:44
overexchangeoverexchange
1,59852347
1,59852347
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Using nonlocal
rather than global
is certainly good, but better yet would be returning values.
def paths(m, n):
def find_number_of_paths(x, y):
if x == 0 and y == 0:
return 1
ret = 0
if x > 0:
ret += find_number_of_paths(x-1, y)
if y > 0:
ret += find_number_of_paths(x, y-1)
return ret
return find_number_of_paths(m-1, n-1)
That lets us elide the outer function entirely:
def paths(x, y):
if x == 1 and y == 1:
return 1
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
return ret
It's a bit strange to critique this since "no closed-form solution" basically means no good solution. There are ways of speeding this up, though, that avoid that. A trivial one is memoization:
_paths_cache = {(1, 1): 1}
def paths(x, y):
if (x, y) in _paths_cache:
return _paths_cache[x, y]
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
_paths_cache[x, y] = ret
return ret
What is closed-form solution?
– overexchange
Jun 30 '15 at 12:34
So, ret=0, executes only once?
– overexchange
Jun 30 '15 at 12:35
${(x-1) + (y-1)} choose {y-1}$
– Veedrac
Jun 30 '15 at 13:35
ret = 0
executes nearly once per call topaths
, which is approximately $xy$ times.
– Veedrac
Jun 30 '15 at 13:40
1
Each call to the function has a differentret
. Look at each function call in isolation:find_number_of_paths(4, 3)
is equal tofind_number_of_paths(3, 3) + find_number_of_paths(4, 2)
, so we add each toret
and return the answer.
– Veedrac
Jul 1 '15 at 0:28
|
show 4 more comments
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f95209%2finsect-combinatorics-challenge%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Using nonlocal
rather than global
is certainly good, but better yet would be returning values.
def paths(m, n):
def find_number_of_paths(x, y):
if x == 0 and y == 0:
return 1
ret = 0
if x > 0:
ret += find_number_of_paths(x-1, y)
if y > 0:
ret += find_number_of_paths(x, y-1)
return ret
return find_number_of_paths(m-1, n-1)
That lets us elide the outer function entirely:
def paths(x, y):
if x == 1 and y == 1:
return 1
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
return ret
It's a bit strange to critique this since "no closed-form solution" basically means no good solution. There are ways of speeding this up, though, that avoid that. A trivial one is memoization:
_paths_cache = {(1, 1): 1}
def paths(x, y):
if (x, y) in _paths_cache:
return _paths_cache[x, y]
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
_paths_cache[x, y] = ret
return ret
What is closed-form solution?
– overexchange
Jun 30 '15 at 12:34
So, ret=0, executes only once?
– overexchange
Jun 30 '15 at 12:35
${(x-1) + (y-1)} choose {y-1}$
– Veedrac
Jun 30 '15 at 13:35
ret = 0
executes nearly once per call topaths
, which is approximately $xy$ times.
– Veedrac
Jun 30 '15 at 13:40
1
Each call to the function has a differentret
. Look at each function call in isolation:find_number_of_paths(4, 3)
is equal tofind_number_of_paths(3, 3) + find_number_of_paths(4, 2)
, so we add each toret
and return the answer.
– Veedrac
Jul 1 '15 at 0:28
|
show 4 more comments
Using nonlocal
rather than global
is certainly good, but better yet would be returning values.
def paths(m, n):
def find_number_of_paths(x, y):
if x == 0 and y == 0:
return 1
ret = 0
if x > 0:
ret += find_number_of_paths(x-1, y)
if y > 0:
ret += find_number_of_paths(x, y-1)
return ret
return find_number_of_paths(m-1, n-1)
That lets us elide the outer function entirely:
def paths(x, y):
if x == 1 and y == 1:
return 1
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
return ret
It's a bit strange to critique this since "no closed-form solution" basically means no good solution. There are ways of speeding this up, though, that avoid that. A trivial one is memoization:
_paths_cache = {(1, 1): 1}
def paths(x, y):
if (x, y) in _paths_cache:
return _paths_cache[x, y]
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
_paths_cache[x, y] = ret
return ret
What is closed-form solution?
– overexchange
Jun 30 '15 at 12:34
So, ret=0, executes only once?
– overexchange
Jun 30 '15 at 12:35
${(x-1) + (y-1)} choose {y-1}$
– Veedrac
Jun 30 '15 at 13:35
ret = 0
executes nearly once per call topaths
, which is approximately $xy$ times.
– Veedrac
Jun 30 '15 at 13:40
1
Each call to the function has a differentret
. Look at each function call in isolation:find_number_of_paths(4, 3)
is equal tofind_number_of_paths(3, 3) + find_number_of_paths(4, 2)
, so we add each toret
and return the answer.
– Veedrac
Jul 1 '15 at 0:28
|
show 4 more comments
Using nonlocal
rather than global
is certainly good, but better yet would be returning values.
def paths(m, n):
def find_number_of_paths(x, y):
if x == 0 and y == 0:
return 1
ret = 0
if x > 0:
ret += find_number_of_paths(x-1, y)
if y > 0:
ret += find_number_of_paths(x, y-1)
return ret
return find_number_of_paths(m-1, n-1)
That lets us elide the outer function entirely:
def paths(x, y):
if x == 1 and y == 1:
return 1
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
return ret
It's a bit strange to critique this since "no closed-form solution" basically means no good solution. There are ways of speeding this up, though, that avoid that. A trivial one is memoization:
_paths_cache = {(1, 1): 1}
def paths(x, y):
if (x, y) in _paths_cache:
return _paths_cache[x, y]
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
_paths_cache[x, y] = ret
return ret
Using nonlocal
rather than global
is certainly good, but better yet would be returning values.
def paths(m, n):
def find_number_of_paths(x, y):
if x == 0 and y == 0:
return 1
ret = 0
if x > 0:
ret += find_number_of_paths(x-1, y)
if y > 0:
ret += find_number_of_paths(x, y-1)
return ret
return find_number_of_paths(m-1, n-1)
That lets us elide the outer function entirely:
def paths(x, y):
if x == 1 and y == 1:
return 1
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
return ret
It's a bit strange to critique this since "no closed-form solution" basically means no good solution. There are ways of speeding this up, though, that avoid that. A trivial one is memoization:
_paths_cache = {(1, 1): 1}
def paths(x, y):
if (x, y) in _paths_cache:
return _paths_cache[x, y]
ret = 0
if x > 1:
ret += paths(x-1, y)
if y > 1:
ret += paths(x, y-1)
_paths_cache[x, y] = ret
return ret
answered Jun 30 '15 at 9:56
VeedracVeedrac
9,1131634
9,1131634
What is closed-form solution?
– overexchange
Jun 30 '15 at 12:34
So, ret=0, executes only once?
– overexchange
Jun 30 '15 at 12:35
${(x-1) + (y-1)} choose {y-1}$
– Veedrac
Jun 30 '15 at 13:35
ret = 0
executes nearly once per call topaths
, which is approximately $xy$ times.
– Veedrac
Jun 30 '15 at 13:40
1
Each call to the function has a differentret
. Look at each function call in isolation:find_number_of_paths(4, 3)
is equal tofind_number_of_paths(3, 3) + find_number_of_paths(4, 2)
, so we add each toret
and return the answer.
– Veedrac
Jul 1 '15 at 0:28
|
show 4 more comments
What is closed-form solution?
– overexchange
Jun 30 '15 at 12:34
So, ret=0, executes only once?
– overexchange
Jun 30 '15 at 12:35
${(x-1) + (y-1)} choose {y-1}$
– Veedrac
Jun 30 '15 at 13:35
ret = 0
executes nearly once per call topaths
, which is approximately $xy$ times.
– Veedrac
Jun 30 '15 at 13:40
1
Each call to the function has a differentret
. Look at each function call in isolation:find_number_of_paths(4, 3)
is equal tofind_number_of_paths(3, 3) + find_number_of_paths(4, 2)
, so we add each toret
and return the answer.
– Veedrac
Jul 1 '15 at 0:28
What is closed-form solution?
– overexchange
Jun 30 '15 at 12:34
What is closed-form solution?
– overexchange
Jun 30 '15 at 12:34
So, ret=0, executes only once?
– overexchange
Jun 30 '15 at 12:35
So, ret=0, executes only once?
– overexchange
Jun 30 '15 at 12:35
${(x-1) + (y-1)} choose {y-1}$
– Veedrac
Jun 30 '15 at 13:35
${(x-1) + (y-1)} choose {y-1}$
– Veedrac
Jun 30 '15 at 13:35
ret = 0
executes nearly once per call to paths
, which is approximately $xy$ times.– Veedrac
Jun 30 '15 at 13:40
ret = 0
executes nearly once per call to paths
, which is approximately $xy$ times.– Veedrac
Jun 30 '15 at 13:40
1
1
Each call to the function has a different
ret
. Look at each function call in isolation: find_number_of_paths(4, 3)
is equal to find_number_of_paths(3, 3) + find_number_of_paths(4, 2)
, so we add each to ret
and return the answer.– Veedrac
Jul 1 '15 at 0:28
Each call to the function has a different
ret
. Look at each function call in isolation: find_number_of_paths(4, 3)
is equal to find_number_of_paths(3, 3) + find_number_of_paths(4, 2)
, so we add each to ret
and return the answer.– Veedrac
Jul 1 '15 at 0:28
|
show 4 more comments
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.
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f95209%2finsect-combinatorics-challenge%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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