Skip to content

Commit

Permalink
[Hacker Rank] Interview Preparation Kit: Recursion: Davis' Staircase.…
Browse files Browse the repository at this point in the history
… Clean code improvements and new generalized solution.
  • Loading branch information
Gonzalo Diaz committed Aug 7, 2024
1 parent a0ab698 commit 9970a1b
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,30 @@ so that repeated cases are not recalculated.

The trade-off is that the algorithm now requires
more memory to run in less time.

## Generalized solution

In order to comply with some clean code best practices,
I noticed that the step limit in the algorithm is a hard-coded number,
so to comply with the "no magic numbers" rule,
I was forced to find a more generalized solution.

Then I found the following pattern:

- First cases are:
$ \text{stepPerms(0)} = 0 $
$ \text{stepPerms(1)} = 1 $
$ \text{stepPerms(2)} = 2 $

- Next step combinations above 2 and less than the step limit are:
$$ \text{stepPerms(number of steps)} = 2^\text{number of steps} + 1 $$

- When $ \text{number of steps} $ are above the limit, the pattern is
the sum of latest $ \text{number of steps} $ previous calls
$ \text{stepPerms}(x) $ results as follows:

$$ \displaystyle\sum_{
i=\text{number of steps} - \text{limit}}
^\text{number of steps}
stepPerms(\text{number of steps} - i)
$$
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { describe, expect, it } from '@jest/globals';
import { logger as console } from '../../../logger';

import { stepPerms } from './ctci_recursive_staircase';
import {
stepPerms,
step_perms_comput_with_cache
} from './ctci_recursive_staircase';
import TEST_CASES from './ctci_recursive_staircase.testcases.json';
import TEST_CASES_GENERALIZED from './ctci_recursive_staircase_generalized.testcases.json';

describe('ctci_recursive_staircase', () => {
it('stepPerms test cases', () => {
Expand All @@ -18,4 +22,25 @@ describe('ctci_recursive_staircase', () => {
});
});
});

it('step_perms_comput_with_cache test cases', () => {
expect.assertions(3);

TEST_CASES_GENERALIZED.forEach((testSet) => {
testSet?.tests.forEach((test) => {
const initial_cache: Record<number, number> = {};
const answer = step_perms_comput_with_cache(
test.input,
initial_cache,
test.limit
);

console.debug(
`step_perms_comput_with_cache(${test.input}, ${initial_cache}, ${test.limit}) solution found: ${answer}`
);

expect(answer).toStrictEqual(test.expected);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,42 @@
* @see Solution Notes: [[docs/hackerrank/interview_preparation_kit/recursion_and_backtracking/ctci-recursive-staircase-solution-notes.md]]
*/

function step_perms_comput_with_cache(
const TOP_LIMIT = 10 ** 10 + 7;
const STEPS_LIMIT = 3;

export function step_perms_comput_with_cache(
n_steps: number,
cache: Record<number, number>
cache: Record<number, number>,
steps_limit: 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++) {
for (let i = 1; i <= Math.min(steps_limit, n_steps); i++) {
const searchKey = n_steps - i;
if (!keys.has(searchKey)) {
cache[n_steps - i] = step_perms_comput_with_cache(searchKey, cache);
cache[searchKey] = step_perms_comput_with_cache(
searchKey,
cache,
steps_limit
);
}

result += cache[searchKey];
}

return result;
return result + (n_steps <= steps_limit ? 1 : 0);
}

export function stepPerms(n: number): number {
const initial_cache: Record<number, number> = {};
return step_perms_comput_with_cache(n, initial_cache) % (10 ** 10 + 7);
return (
step_perms_comput_with_cache(n, initial_cache, STEPS_LIMIT) % TOP_LIMIT
);
}

export default { stepPerms };
export default { stepPerms, step_perms_comput_with_cache };
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[
{
"title": "Own sample 1",
"tests": [
{
"input": 4,
"limit": 3,
"expected": 7
}
]
},
{
"title": "Own sample 2",
"tests": [
{
"input": 5,
"limit": 4,
"expected": 15
}
]
},
{
"title": "Own sample 3",
"tests": [
{
"input": 6,
"limit": 2,
"expected": 13
}
]
}
]

0 comments on commit 9970a1b

Please sign in to comment.