-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Hacker Rank] Interview Preparation Kit: Recursion: Davis' Staircase.…
… Solved ✅.
- Loading branch information
Gonzalo Diaz
committed
Aug 6, 2024
1 parent
245ca59
commit a0ab698
Showing
5 changed files
with
255 additions
and
0 deletions.
There are no files selected for viewing
42 changes: 42 additions & 0 deletions
42
...ation_kit/recursion_and_backtracking/ctci-recursive-staircase-solution-notes.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# [Recursion: Davis' Staircase](https://www.hackerrank.com/challenges/ctci-recursive-staircase) | ||
|
||
Find the number of ways to get from the bottom of a staircase | ||
to the top if you can jump 1, 2, or 3 stairs at a time. | ||
|
||
- Difficulty: `#medium` | ||
- Category: `#ProblemSolvingIntermediate` | ||
|
||
## Failed solution | ||
|
||
This solution correctly calculates the result. The problem is its performance, | ||
since due to the traversal of the recursion tree, | ||
it is eventually easy to reach repeated cases that are recalculated each time. | ||
|
||
```typescript | ||
def step_perms_compute(n: number): number | ||
if (n == 0) { | ||
return 0 | ||
} | ||
if (n == 1) { | ||
return 1 | ||
} | ||
if (n == 2) { | ||
return 2 | ||
} | ||
if (n == 3) { | ||
return 4 | ||
} | ||
|
||
return | ||
step_perms_compute(n - 3) + | ||
step_perms_compute(n - 2) + | ||
step_perms_compute(n - 1) | ||
``` | ||
|
||
## Alternative solution | ||
|
||
The final solution introduces a simple caching mechanism, | ||
so that repeated cases are not recalculated. | ||
|
||
The trade-off is that the algorithm now requires | ||
more memory to run in less time. |
105 changes: 105 additions & 0 deletions
105
...nterview_preparation_kit/recursion_and_backtracking/ctci-recursive-staircase.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# [Recursion: Davis' Staircase](https://www.hackerrank.com/challenges/ctci-recursive-staircase) | ||
|
||
Find the number of ways to get from the bottom of a staircase | ||
to the top if you can jump 1, 2, or 3 stairs at a time. | ||
|
||
- Difficulty: `#medium` | ||
- Category: `#ProblemSolvingIntermediate` | ||
|
||
Davis has a number of staircases in his house and he likes to | ||
climb each staircase `1`, `2`, or `3` steps at a time. | ||
Being a very precocious child, he wonders how many ways there | ||
are to reach the top of the staircase. | ||
|
||
Given the respective heights for each of the staircases in his house, | ||
find and print the number of ways he can climb each staircase, | ||
module $10^10 + 7 $ on a new line. | ||
|
||
## Example | ||
|
||
`n = 5` | ||
|
||
The staircase has `5` steps. Davis can step on the following sequences of steps: | ||
|
||
```text | ||
1 1 1 1 1 | ||
1 1 1 2 | ||
1 1 2 1 | ||
1 2 1 1 | ||
2 1 1 1 | ||
1 2 2 | ||
2 2 1 | ||
2 1 2 | ||
1 1 3 | ||
1 3 1 | ||
3 1 1 | ||
2 3 | ||
3 2 | ||
``` | ||
|
||
There are `13` possible ways he can take these `5` steps and `13 modulo 10000000007` | ||
|
||
## Function Description | ||
|
||
Complete the stepPerms function using recursion in the editor below. | ||
|
||
stepPerms has the following parameter(s): | ||
|
||
- int n: the number of stairs in the staircase | ||
|
||
## Returns | ||
|
||
int: the number of ways Davis can climb the staircase, modulo 10000000007 | ||
|
||
## Input Format | ||
|
||
The first line contains a single integer, `s`, the number of staircases in his house. | ||
Each of the following `s` lines contains a single integer, | ||
`n`, the height of staircase `i`. | ||
|
||
## Constraints | ||
|
||
- $ 1 \leq s \leq 5 $ | ||
- $ 1 \leq n \leq 36 $ | ||
|
||
## Subtasks | ||
|
||
- 1 \leq n \leq 20 for `50%` of the maximum score. | ||
|
||
## Sample Input | ||
|
||
```text | ||
STDIN Function | ||
----- -------- | ||
3 s = 3 (number of staircases) | ||
1 first staircase n = 1 | ||
3 second n = 3 | ||
7 third n = 7 | ||
``` | ||
|
||
## Sample Output | ||
|
||
```text | ||
1 | ||
4 | ||
44 | ||
``` | ||
|
||
## Explanation | ||
|
||
Let's calculate the number of ways of climbing | ||
the first two of the Davis' `s = 3` staircases: | ||
|
||
1. The first staircase only has `n = 1` step, | ||
so there is only one way for him to | ||
climb it (i.e., by jumping `1` step). Thus, we print `1` on a new line. | ||
|
||
2. The second staircase has `n = 3` steps and he can climb it in any of the | ||
four following ways: | ||
|
||
1. 1 -> 1 -> 1 | ||
2. 1 -> 2 | ||
3. 2 -> 1 | ||
4. 3 | ||
|
||
Thus, we print `4` on a new line. |
21 changes: 21 additions & 0 deletions
21
...ank/interview_preparation_kit/recursion_and_backtracking/ctci_recursive_staircase.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { describe, expect, it } from '@jest/globals'; | ||
import { logger as console } from '../../../logger'; | ||
|
||
import { stepPerms } from './ctci_recursive_staircase'; | ||
import TEST_CASES from './ctci_recursive_staircase.testcases.json'; | ||
|
||
describe('ctci_recursive_staircase', () => { | ||
it('stepPerms test cases', () => { | ||
expect.assertions(8); | ||
|
||
TEST_CASES.forEach((testSet) => { | ||
testSet?.tests.forEach((test) => { | ||
const answer = stepPerms(test.input); | ||
|
||
console.debug(`stepPerms(${test.input}) solution found: ${answer}`); | ||
|
||
expect(answer).toStrictEqual(test.expected); | ||
}); | ||
}); | ||
}); | ||
}); |
49 changes: 49 additions & 0 deletions
49
...erview_preparation_kit/recursion_and_backtracking/ctci_recursive_staircase.testcases.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
[ | ||
{ | ||
"title": "Sample Test case 0", | ||
"tests": [ | ||
{ | ||
"input": 1, | ||
"expected": 1 | ||
}, | ||
{ | ||
"input": 3, | ||
"expected": 4 | ||
}, | ||
{ | ||
"input": 7, | ||
"expected": 44 | ||
} | ||
] | ||
}, | ||
{ | ||
"title": "Sample Test case 9", | ||
"tests": [ | ||
{ | ||
"input": 5, | ||
"expected": 13 | ||
}, | ||
{ | ||
"input": 8, | ||
"expected": 81 | ||
} | ||
] | ||
}, | ||
{ | ||
"title": "Sample Test case 10", | ||
"tests": [ | ||
{ | ||
"input": 15, | ||
"expected": 5768 | ||
}, | ||
{ | ||
"input": 20, | ||
"expected": 121415 | ||
}, | ||
{ | ||
"input": 27, | ||
"expected": 8646064 | ||
} | ||
] | ||
} | ||
] |
38 changes: 38 additions & 0 deletions
38
...ckerrank/interview_preparation_kit/recursion_and_backtracking/ctci_recursive_staircase.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* @link Problem definition [[docs/hackerrank/interview_preparation_kit/recursion_and_backtracking/ctci-recursive-staircase.md]] | ||
* @see Solution Notes: [[docs/hackerrank/interview_preparation_kit/recursion_and_backtracking/ctci-recursive-staircase-solution-notes.md]] | ||
*/ | ||
|
||
function step_perms_comput_with_cache( | ||
n_steps: number, | ||
cache: Record<number, number> | ||
): number { | ||
if (0 <= n_steps && n_steps <= 2) { | ||
return n_steps; | ||
} | ||
|
||
if (n_steps == 3) { | ||
return 4; | ||
} | ||
|
||
const keys = new Set(Object.values(cache)); | ||
let result = 0; | ||
|
||
for (let i = 1; i < 4; i++) { | ||
const searchKey = n_steps - i; | ||
if (!keys.has(searchKey)) { | ||
cache[n_steps - i] = step_perms_comput_with_cache(searchKey, cache); | ||
} | ||
|
||
result += cache[searchKey]; | ||
} | ||
|
||
return result; | ||
} | ||
|
||
export function stepPerms(n: number): number { | ||
const initial_cache: Record<number, number> = {}; | ||
return step_perms_comput_with_cache(n, initial_cache) % (10 ** 10 + 7); | ||
} | ||
|
||
export default { stepPerms }; |