Skip to content

Commit 77620c7

Browse files
authored
Merge pull request #427 from sir-gon/feature/ctci-recursive-staircase
[Hacker Rank] Interview Preparation Kit: Recursion: Davis' Staircase.…
2 parents 245ca59 + a0ab698 commit 77620c7

File tree

5 files changed

+255
-0
lines changed

5 files changed

+255
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# [Recursion: Davis' Staircase](https://www.hackerrank.com/challenges/ctci-recursive-staircase)
2+
3+
Find the number of ways to get from the bottom of a staircase
4+
to the top if you can jump 1, 2, or 3 stairs at a time.
5+
6+
- Difficulty: `#medium`
7+
- Category: `#ProblemSolvingIntermediate`
8+
9+
## Failed solution
10+
11+
This solution correctly calculates the result. The problem is its performance,
12+
since due to the traversal of the recursion tree,
13+
it is eventually easy to reach repeated cases that are recalculated each time.
14+
15+
```typescript
16+
def step_perms_compute(n: number): number
17+
if (n == 0) {
18+
return 0
19+
}
20+
if (n == 1) {
21+
return 1
22+
}
23+
if (n == 2) {
24+
return 2
25+
}
26+
if (n == 3) {
27+
return 4
28+
}
29+
30+
return
31+
step_perms_compute(n - 3) +
32+
step_perms_compute(n - 2) +
33+
step_perms_compute(n - 1)
34+
```
35+
36+
## Alternative solution
37+
38+
The final solution introduces a simple caching mechanism,
39+
so that repeated cases are not recalculated.
40+
41+
The trade-off is that the algorithm now requires
42+
more memory to run in less time.
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# [Recursion: Davis' Staircase](https://www.hackerrank.com/challenges/ctci-recursive-staircase)
2+
3+
Find the number of ways to get from the bottom of a staircase
4+
to the top if you can jump 1, 2, or 3 stairs at a time.
5+
6+
- Difficulty: `#medium`
7+
- Category: `#ProblemSolvingIntermediate`
8+
9+
Davis has a number of staircases in his house and he likes to
10+
climb each staircase `1`, `2`, or `3` steps at a time.
11+
Being a very precocious child, he wonders how many ways there
12+
are to reach the top of the staircase.
13+
14+
Given the respective heights for each of the staircases in his house,
15+
find and print the number of ways he can climb each staircase,
16+
module $10^10 + 7 $ on a new line.
17+
18+
## Example
19+
20+
`n = 5`
21+
22+
The staircase has `5` steps. Davis can step on the following sequences of steps:
23+
24+
```text
25+
1 1 1 1 1
26+
1 1 1 2
27+
1 1 2 1
28+
1 2 1 1
29+
2 1 1 1
30+
1 2 2
31+
2 2 1
32+
2 1 2
33+
1 1 3
34+
1 3 1
35+
3 1 1
36+
2 3
37+
3 2
38+
```
39+
40+
There are `13` possible ways he can take these `5` steps and `13 modulo 10000000007`
41+
42+
## Function Description
43+
44+
Complete the stepPerms function using recursion in the editor below.
45+
46+
stepPerms has the following parameter(s):
47+
48+
- int n: the number of stairs in the staircase
49+
50+
## Returns
51+
52+
int: the number of ways Davis can climb the staircase, modulo 10000000007
53+
54+
## Input Format
55+
56+
The first line contains a single integer, `s`, the number of staircases in his house.
57+
Each of the following `s` lines contains a single integer,
58+
`n`, the height of staircase `i`.
59+
60+
## Constraints
61+
62+
- $ 1 \leq s \leq 5 $
63+
- $ 1 \leq n \leq 36 $
64+
65+
## Subtasks
66+
67+
- 1 \leq n \leq 20 for `50%` of the maximum score.
68+
69+
## Sample Input
70+
71+
```text
72+
STDIN Function
73+
----- --------
74+
3 s = 3 (number of staircases)
75+
1 first staircase n = 1
76+
3 second n = 3
77+
7 third n = 7
78+
```
79+
80+
## Sample Output
81+
82+
```text
83+
1
84+
4
85+
44
86+
```
87+
88+
## Explanation
89+
90+
Let's calculate the number of ways of climbing
91+
the first two of the Davis' `s = 3` staircases:
92+
93+
1. The first staircase only has `n = 1` step,
94+
so there is only one way for him to
95+
climb it (i.e., by jumping `1` step). Thus, we print `1` on a new line.
96+
97+
2. The second staircase has `n = 3` steps and he can climb it in any of the
98+
four following ways:
99+
100+
1. 1 -> 1 -> 1
101+
2. 1 -> 2
102+
3. 2 -> 1
103+
4. 3
104+
105+
Thus, we print `4` on a new line.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { describe, expect, it } from '@jest/globals';
2+
import { logger as console } from '../../../logger';
3+
4+
import { stepPerms } from './ctci_recursive_staircase';
5+
import TEST_CASES from './ctci_recursive_staircase.testcases.json';
6+
7+
describe('ctci_recursive_staircase', () => {
8+
it('stepPerms test cases', () => {
9+
expect.assertions(8);
10+
11+
TEST_CASES.forEach((testSet) => {
12+
testSet?.tests.forEach((test) => {
13+
const answer = stepPerms(test.input);
14+
15+
console.debug(`stepPerms(${test.input}) solution found: ${answer}`);
16+
17+
expect(answer).toStrictEqual(test.expected);
18+
});
19+
});
20+
});
21+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
[
2+
{
3+
"title": "Sample Test case 0",
4+
"tests": [
5+
{
6+
"input": 1,
7+
"expected": 1
8+
},
9+
{
10+
"input": 3,
11+
"expected": 4
12+
},
13+
{
14+
"input": 7,
15+
"expected": 44
16+
}
17+
]
18+
},
19+
{
20+
"title": "Sample Test case 9",
21+
"tests": [
22+
{
23+
"input": 5,
24+
"expected": 13
25+
},
26+
{
27+
"input": 8,
28+
"expected": 81
29+
}
30+
]
31+
},
32+
{
33+
"title": "Sample Test case 10",
34+
"tests": [
35+
{
36+
"input": 15,
37+
"expected": 5768
38+
},
39+
{
40+
"input": 20,
41+
"expected": 121415
42+
},
43+
{
44+
"input": 27,
45+
"expected": 8646064
46+
}
47+
]
48+
}
49+
]
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* @link Problem definition [[docs/hackerrank/interview_preparation_kit/recursion_and_backtracking/ctci-recursive-staircase.md]]
3+
* @see Solution Notes: [[docs/hackerrank/interview_preparation_kit/recursion_and_backtracking/ctci-recursive-staircase-solution-notes.md]]
4+
*/
5+
6+
function step_perms_comput_with_cache(
7+
n_steps: number,
8+
cache: Record<number, number>
9+
): number {
10+
if (0 <= n_steps && n_steps <= 2) {
11+
return n_steps;
12+
}
13+
14+
if (n_steps == 3) {
15+
return 4;
16+
}
17+
18+
const keys = new Set(Object.values(cache));
19+
let result = 0;
20+
21+
for (let i = 1; i < 4; i++) {
22+
const searchKey = n_steps - i;
23+
if (!keys.has(searchKey)) {
24+
cache[n_steps - i] = step_perms_comput_with_cache(searchKey, cache);
25+
}
26+
27+
result += cache[searchKey];
28+
}
29+
30+
return result;
31+
}
32+
33+
export function stepPerms(n: number): number {
34+
const initial_cache: Record<number, number> = {};
35+
return step_perms_comput_with_cache(n, initial_cache) % (10 ** 10 + 7);
36+
}
37+
38+
export default { stepPerms };

0 commit comments

Comments
 (0)