Skip to content

Commit 22d4f62

Browse files
committed
Update Grid Traveller
1 parent 59d0d00 commit 22d4f62

File tree

3 files changed

+80
-106
lines changed

3 files changed

+80
-106
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import gridTraveller from './grid-traveller';
2+
3+
const parameters = [
4+
{ rows: 0, columns: 0, expected: 0 },
5+
{ rows: 0, columns: 1, expected: 0 },
6+
{ rows: 1, columns: 0, expected: 0 },
7+
{ rows: 1, columns: 1, expected: 1 },
8+
{ rows: 1, columns: 2, expected: 1 },
9+
{ rows: 2, columns: 1, expected: 1 },
10+
{ rows: 2, columns: 2, expected: 2 },
11+
{ rows: 2, columns: 3, expected: 3 },
12+
{ rows: 3, columns: 2, expected: 3 },
13+
{ rows: 3, columns: 3, expected: 6 },
14+
{ rows: 3, columns: 4, expected: 10 },
15+
{ rows: 4, columns: 3, expected: 10 },
16+
{ rows: 4, columns: 4, expected: 20 },
17+
{ rows: 4, columns: 5, expected: 35 },
18+
{ rows: 5, columns: 4, expected: 35 },
19+
{ rows: 5, columns: 5, expected: 70 },
20+
{ rows: 5, columns: 6, expected: 126 },
21+
{ rows: 6, columns: 5, expected: 126 },
22+
{ rows: 6, columns: 6, expected: 252 },
23+
{ rows: 6, columns: 7, expected: 462 },
24+
{ rows: 7, columns: 6, expected: 462 },
25+
{ rows: 7, columns: 7, expected: 924 },
26+
{ rows: 7, columns: 8, expected: 1716 },
27+
{ rows: 8, columns: 7, expected: 1716 },
28+
{ rows: 8, columns: 8, expected: 3432 },
29+
{ rows: 8, columns: 9, expected: 6435 },
30+
{ rows: 9, columns: 8, expected: 6435 },
31+
{ rows: 9, columns: 9, expected: 12870 },
32+
{ rows: 9, columns: 10, expected: 24310 },
33+
{ rows: 10, columns: 9, expected: 24310 },
34+
{ rows: 10, columns: 10, expected: 48620 },
35+
{ rows: 20, columns: 20, expected: 35345263800 },
36+
{ rows: 30, columns: 30, expected: 30067266499541040 },
37+
{ rows: 40, columns: 40, expected: 2.7217014869199036e+22 },
38+
{ rows: 50, columns: 50, expected: 2.5477612258980867e+28 },
39+
{ rows: 60, columns: 60, expected: 2.4356699707654625e+34 },
40+
{ rows: 70, columns: 70, expected: 2.362398517571512e+40 },
41+
{ rows: 80, columns: 80, expected: 2.3156006494021195e+46 },
42+
{ rows: 90, columns: 90, expected: 2.288017424736007e+52 },
43+
{ rows: 100, columns: 100, expected: 2.2750883079422938e+58 },
44+
];
45+
46+
test.each(parameters)(
47+
'gridTraveller($rows, $columns) = $expected',
48+
({ rows, columns, expected }) => {
49+
expect(gridTraveller(rows, columns)).toEqual(expected);
50+
}
51+
);
Lines changed: 29 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,46 @@
11
/**
2-
* - Time complexity: O(2^n+m)
3-
* - Space complexity: O(n+m)
42
*
5-
* where "n" is the number of rows and "m" the number of columns.
6-
*
7-
* @param rows the number of rows of the grid.
8-
* @param columns the number of columns of the grid.
9-
*/
10-
function bruteForceGridTraveller(rows: number, columns: number): number {
11-
if (rows === 0 || columns === 0) return 0;
12-
if (rows === 1 && columns === 1) return 1;
13-
14-
return bruteForceGridTraveller(rows - 1, columns) + bruteForceGridTraveller(rows, columns - 1);
15-
}
16-
17-
/**
18-
* - Time complexity: O(n+m)
19-
* - Space complexity: O(n+m)
20-
*
21-
* where "n" is the number of rows and "m" the number of columns.
22-
*
23-
* @param rows the number of rows of the grid.
24-
* @param columns the number of columns of the grid.
25-
* @param buffer buffer object used for memoisation.
3+
* @param rows the number of rows of the grid
4+
* @param columns the number of columns of the grid
5+
* @param buffer the buffer used for memoisation
6+
* @returns how many ways there are to travel on a n by m grid
267
*/
27-
function memoisedGridTraveller(
28-
rows: number,
29-
columns: number,
30-
buffer: { [key: string]: number } = {}
31-
): number {
32-
const key = `${rows}-${columns}`;
8+
export default function gridTraveller(rows: number, columns: number, buffer: object = {}): number {
9+
const key = getKey(rows, columns);
3310
if (key in buffer) return buffer[key];
3411
if (rows <= 0 || columns <= 0) return 0;
35-
if (rows === 1 && columns === 1) return 1;
12+
if (rows === 1 || columns === 1) return 1;
3613

3714
buffer[key] =
38-
memoisedGridTraveller(rows - 1, columns, buffer) +
39-
memoisedGridTraveller(rows, columns - 1, buffer);
15+
// travels down in the grid (decrement the row)
16+
gridTraveller(rows - 1, columns, buffer) +
17+
// travels right in the grid (decrement the column)
18+
gridTraveller(rows, columns - 1, buffer);
19+
4020
return buffer[key];
4121
}
4222

4323
/**
24+
* Return a key built out of the input parameters.
25+
*
26+
* This snippet creates a key to de-dupe the entries in the buffer.
27+
*
28+
* The key uses a separator to prevent collisions. Without separator
29+
* we may have this situation "789" where it is unclear whether
30+
* n = 7 and m = 89 or n = 78 and m = 9
31+
*
32+
* Given (n = 7, m = 3) and (n = 3, m = 7) have the same result,
33+
* the ksy is also normalised with the first element before the
34+
* separator being less or equal than the second element.
4435
*
36+
* @param rows the number of rows of the grid
37+
* @param columns the number of columns of the grid
38+
* @returns a key to be used in the buffer object
4539
*/
46-
function dedupedGridTraveller(
47-
rows: number,
48-
columns: number,
49-
buffer: { [key: string]: number } = {}
50-
): number {
51-
let key = `${rows}-${columns}`;
40+
function getKey(rows: number, columns: number) {
5241
if (columns < rows) {
53-
key = `${columns}-${rows}`;
54-
}
55-
if (key in buffer) return buffer[key];
56-
if (rows <= 0 || columns <= 0) return 0;
57-
if (rows === 1 && columns === 1) return 1;
58-
59-
buffer[key] =
60-
dedupedGridTraveller(rows - 1, columns, buffer) +
61-
dedupedGridTraveller(rows, columns - 1, buffer);
62-
return buffer[key];
63-
}
64-
65-
/**
66-
* @param rows the number of rows of the grid.
67-
* @param columns the number of columns of the grid.
68-
* @param memoised true to optimise the recursive function by caching the intermediate responses.
69-
* @param deduped true to optimise the recursive function by removing duplicate branch in the tree.
70-
*/
71-
export interface GridTravellerParameters {
72-
rows: number;
73-
columns: number;
74-
memoised?: boolean;
75-
deduped?: boolean;
76-
}
77-
78-
/**
79-
* Returns the number of path reachable from the top left corner to the bottom right one in a N x M grid.
80-
*/
81-
export default function gridTraveller(parameters: GridTravellerParameters): number {
82-
const { rows, columns, memoised, deduped } = parameters;
83-
84-
if (deduped) {
85-
return dedupedGridTraveller(rows, columns);
86-
}
87-
88-
if (memoised) {
89-
return memoisedGridTraveller(rows, columns);
42+
return `${columns}-${rows}`;
9043
}
9144

92-
return bruteForceGridTraveller(rows, columns);
45+
return `${rows}-${columns}`;
9346
}

test/algorithms/dynamic-programming/grid-traveller.test.ts

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)