Skip to content

Commit 8586556

Browse files
author
Gonzalo Diaz
committed
[REFACTOR] [Hacker Rank] Interview Preparation Kit: Search: Swap Nodes [Algo]. Solved as OOP ✅.
1 parent 4b7ef7a commit 8586556

File tree

3 files changed

+79
-114
lines changed

3 files changed

+79
-114
lines changed

src/hackerrank/interview_preparation_kit/search/swap_nodes_algo.big.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import { describe, expect, it } from '@jest/globals';
22

3-
import { swapNodes, buildTree, flatTree } from './swap_nodes_algo.js';
3+
import { Tree, swapNodes } from './swap_nodes_algo.js';
44
import BIG_TEST_CASES from './swap_nodes_algo.big.testcases.json';
55

66
describe('swap_nodes_algo', () => {
77
it('build_tree and plain test cases', () => {
88
expect.assertions(1);
99

1010
BIG_TEST_CASES.forEach((test) => {
11-
const toTest = buildTree(test.nodes);
12-
const tResult = flatTree(toTest);
11+
const tree = new Tree(test.nodes);
12+
const tresult = tree.flatTree();
1313

14-
expect(tResult).toStrictEqual(test.flattened);
14+
expect(tresult).toStrictEqual(test.flattened);
1515
});
1616
});
1717

src/hackerrank/interview_preparation_kit/search/swap_nodes_algo.js

Lines changed: 66 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* @link Problem export functioninition [[docs/hackerrank/interview_preparation_kit/search/swap-nodes-algo.md]]
33
*/
44

5-
import { logger as console } from '../../../logger.js';
65
import { Node } from '../../lib/Node.js';
76

87
// CONSTANTS
@@ -11,137 +10,104 @@ export const __ROOT_VALUE__ = 1;
1110
export const __LEAF_VALUE__ = -1;
1211
const __RADIX__ = 10;
1312

14-
export function callbackCollectNodes(root, collect, level) {
15-
if (root) {
16-
if (collect?.[level] === undefined) {
17-
// eslint-disable-next-line no-param-reassign
18-
collect[level] = [root];
19-
} else {
20-
collect[level].push(root);
21-
}
22-
}
23-
}
13+
export class Tree {
14+
root;
2415

25-
export function traverseInOrderCollector(root, collect, level, callbackFn) {
26-
if (root?.left !== null) {
27-
traverseInOrderCollector(root?.left, collect, level + 1, callbackFn);
28-
}
16+
nodeCollector;
2917

30-
callbackFn(root, collect, level);
18+
constructor(indexes) {
19+
this.root = new Node(__ROOT_VALUE__);
20+
this.nodeCollector = {};
21+
this.nodeCollector[__INITIAL_LEVEL__] = [this.root];
3122

32-
if (root?.right !== null) {
33-
traverseInOrderCollector(root?.right, collect, level + 1, callbackFn);
23+
this.buildTree(indexes);
3424
}
3525

36-
return collect;
37-
}
26+
buildTree(indexes) {
27+
const indexesCopy = [...indexes];
28+
let currentLevel = __INITIAL_LEVEL__;
3829

39-
export function buildTree(indexes) {
40-
const indexesCopy = [...indexes];
41-
const root = new Node(__ROOT_VALUE__);
42-
let currentLevel = 1;
43-
const nodeCollector = {};
44-
nodeCollector[currentLevel] = [root];
45-
46-
while (indexesCopy.length > 0) {
47-
nodeCollector = {};
48-
49-
traverseInOrderCollector(
50-
root,
51-
nodeCollector,
52-
__INITIAL_LEVEL__,
53-
callbackCollectNodes
54-
);
55-
56-
const lastLevel = parseInt(
57-
Object.keys(nodeCollector)
58-
.sort((a, b) => parseInt(b, __RADIX__) - parseInt(a, __RADIX__))
59-
.shift(),
60-
__RADIX__
61-
);
62-
63-
const levelSize = Math.min(
64-
indexesCopy.length,
65-
nodeCollector[currentLevel]?.length
66-
);
67-
68-
const nextLevel = currentLevel + 1;
69-
70-
if (levelSize > 0) {
71-
nodeCollector[nextLevel] = [];
72-
}
30+
while (indexesCopy.length > 0) {
31+
const levelSize = Math.min(
32+
indexesCopy.length,
33+
this.nodeCollector[currentLevel]?.length
34+
);
7335

74-
for (let i = 0; i < levelSize; i++) {
75-
const currentNode = nodeCollector[currentLevel][i];
76-
const newElement = indexesCopy.shift();
36+
const nextLevel = currentLevel + 1;
7737

78-
if ((newElement?.[0] ?? __LEAF_VALUE__) !== __LEAF_VALUE__) {
79-
currentNode.left = new Node(newElement[0]);
80-
nodeCollector[nextLevel].push(currentNode.left);
38+
if (levelSize > 0) {
39+
this.nodeCollector[nextLevel] = [];
8140
}
82-
if ((newElement?.[1] ?? __LEAF_VALUE__) !== __LEAF_VALUE__) {
83-
currentNode.right = new Node(newElement[1]);
84-
nodeCollector[nextLevel].push(currentNode.right);
41+
42+
for (let i = 0; i < levelSize; i++) {
43+
const currentNode = this.nodeCollector[currentLevel][i];
44+
const newElement = indexesCopy.shift();
45+
46+
if ((newElement?.[0] ?? __LEAF_VALUE__) !== __LEAF_VALUE__) {
47+
currentNode.left = new Node(newElement[0]);
48+
this.nodeCollector[nextLevel].push(currentNode.left);
49+
}
50+
if ((newElement?.[1] ?? __LEAF_VALUE__) !== __LEAF_VALUE__) {
51+
currentNode.right = new Node(newElement[1]);
52+
this.nodeCollector[nextLevel].push(currentNode.right);
53+
}
8554
}
86-
}
8755

88-
if (nodeCollector[nextLevel].length > 0) {
89-
currentLevel = nextLevel;
56+
if (this.nodeCollector[nextLevel].length > 0) {
57+
currentLevel = nextLevel;
58+
}
9059
}
60+
61+
return this;
9162
}
9263

93-
return root;
94-
}
64+
getRoot() {
65+
return this.root;
66+
}
9567

96-
export function flatTree(root) {
97-
const nodeCollector = [];
68+
getCollector() {
69+
return this.nodeCollector;
70+
}
9871

99-
function traverseInOrderFlat(node) {
100-
if (node?.left !== null) {
101-
traverseInOrderFlat(node?.left);
102-
}
72+
flatTree() {
73+
const flatTreeCollector = [];
10374

104-
if (node) {
105-
nodeCollector.push(node);
106-
}
75+
function traverseInOrderFlat(node) {
76+
if (node?.left !== null) {
77+
traverseInOrderFlat(node?.left);
78+
}
10779

108-
if (node?.right !== null) {
109-
traverseInOrderFlat(node?.right);
80+
if (node) {
81+
flatTreeCollector.push(node);
82+
}
83+
84+
if (node?.right !== null) {
85+
traverseInOrderFlat(node?.right);
86+
}
11087
}
111-
}
11288

113-
traverseInOrderFlat(root);
89+
traverseInOrderFlat(this.root);
11490

115-
const output = [];
116-
nodeCollector.forEach((node) => {
117-
output.push(node.data);
118-
});
91+
const output = [];
92+
flatTreeCollector.forEach((node) => {
93+
output.push(node.data);
94+
});
11995

120-
return output;
96+
return output;
97+
}
12198
}
12299

123100
export function swapNodes(indexes, queries) {
124-
const tree = buildTree(indexes);
101+
const tree = new Tree(indexes);
102+
let nodeCollector = tree.getCollector();
125103
const output = [];
126-
let nodeCollector = {};
127-
128-
traverseInOrderCollector(
129-
tree,
130-
nodeCollector,
131-
__INITIAL_LEVEL__,
132-
callbackCollectNodes
133-
);
134104

135105
nodeCollector = Object.fromEntries(
136106
Object.entries(nodeCollector).sort(
137107
([a], [b]) => parseInt(a, __RADIX__) - parseInt(b, __RADIX__)
138108
)
139109
);
140110

141-
let flattenedTree = flatTree(tree);
142-
143-
console.debug(`Plain tree: ${flattenedTree}`);
144-
145111
for (const query of queries) {
146112
for (const [level, nodeList] of Object.entries(nodeCollector)) {
147113
const tLevel = parseInt(level, __RADIX__);
@@ -154,8 +120,7 @@ export function swapNodes(indexes, queries) {
154120
}
155121
}
156122

157-
flattenedTree = flatTree(tree);
158-
output.push(flattenedTree);
123+
output.push(tree.flatTree());
159124
}
160125

161126
return output;

src/hackerrank/interview_preparation_kit/search/swap_nodes_algo.test.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
import { describe, expect, it } from '@jest/globals';
22

3-
import { buildTree, flatTree, swapNodes } from './swap_nodes_algo.js';
3+
import { Tree, swapNodes } from './swap_nodes_algo.js';
44
import TESTCASES from './swap_nodes_algo.testcases.json';
55

66
describe('swap_nodes_algo', () => {
77
it('testbuildTree_empty', () => {
8-
expect.assertions(1);
8+
expect.assertions(2);
99

1010
const tInput = [];
11-
const toTest = buildTree(tInput);
12-
const tresult = flatTree(toTest);
11+
const tree = new Tree(tInput);
1312
const expected = [1];
1413

15-
expect(tresult).toStrictEqual(expected);
14+
expect(tree.flatTree()).toStrictEqual(expected);
15+
expect(tree.getRoot()).not.toBeNull();
1616
});
1717

1818
it('testbuild_malformed_tree', () => {
1919
expect.assertions(1);
2020

2121
const input = [[], []];
22-
const toTest = buildTree(input);
23-
const tresult = flatTree(toTest);
22+
const tree = new Tree(input);
23+
const tresult = tree.flatTree();
2424
const expected = [1];
2525

2626
expect(tresult).toStrictEqual(expected);
@@ -30,8 +30,8 @@ describe('swap_nodes_algo', () => {
3030
expect.assertions(4);
3131

3232
TESTCASES.forEach((test) => {
33-
const toTest = buildTree(test.nodes);
34-
const tresult = flatTree(toTest);
33+
const tree = new Tree(test.nodes);
34+
const tresult = tree.flatTree();
3535

3636
expect(tresult).toStrictEqual(test.flattened);
3737
});

0 commit comments

Comments
 (0)