-
Notifications
You must be signed in to change notification settings - Fork 931
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6da8c62
commit 88441c2
Showing
13 changed files
with
10,802 additions
and
5,954 deletions.
There are no files selected for viewing
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,74 @@ | ||
/** | ||
* @param {number} n | ||
* @param {number[][]} connections | ||
* @return {number[][]} | ||
*/ | ||
function criticalConnections(n, connections) { | ||
const critical = []; | ||
const graph = buildGraph(n, connections); | ||
// console.log({graph}) | ||
|
||
for (let i = 0; i < connections.length; i++) { // O(|E| * [|V|^3 + |V|^2|E|]) = O(|V|^3|E| + |V|^2|E|^2) | ||
const link = connections[i]; | ||
if (isLinkCritical(link, graph)) { | ||
critical.push(link); | ||
} | ||
} | ||
|
||
return critical; | ||
} | ||
|
||
function buildGraph(n, connections) { | ||
const graph = [...Array(n).keys()].reduce((map, i) => { | ||
map.set(i, new Set()); | ||
return map; | ||
}, new Map()); | ||
|
||
connections.forEach(([i, j]) => { | ||
const iAdj = graph.get(i); | ||
iAdj.add(j); | ||
const jAdj = graph.get(j); | ||
jAdj.add(i); | ||
}); | ||
|
||
return graph; | ||
} | ||
|
||
function isLinkCritical(link, graph) { // DFS: O(|V|^2 * |E|+|V|) = O(|V|^3 + |V|^2|E|) | ||
for (let i = 0; i < graph.size; i++) { | ||
for (let j = 0; j < graph.size; j++) { | ||
if (hasLink([i, j], link)) continue; | ||
if (!isConnected(i, j, link, graph)) { // DFS: O(|E|+|V|) | ||
// console.log({i, j, link}); | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
function hasLink(a, b) { | ||
return (a[0] === b[0] && a[1] === b[1]) || (a[0] === b[1] && a[1] === b[0]); | ||
} | ||
|
||
// DFS: O(|E|+|V|) | ||
function isConnected(i, j, ignoreLink, graph, seen = new Set()) { | ||
if (i === j) return true; | ||
if (graph.get(i).has(j)) return true; | ||
|
||
for (const adj of graph.get(i)) { | ||
if (hasLink([i, adj], ignoreLink)) continue; | ||
|
||
if (seen.has(adj)) continue; | ||
seen.add(adj); | ||
|
||
if (isConnected(adj, j, ignoreLink, graph, seen)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
module.exports = criticalConnections; |
Large diffs are not rendered by default.
Oops, something went wrong.
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,54 @@ | ||
/** | ||
* @param {number} n | ||
* @param {number[][]} connections | ||
* @return {number[][]} | ||
*/ | ||
function criticalConnections(n, connections) { | ||
const graph = buildGraph(n, connections); | ||
// console.log({graph}) | ||
|
||
return dfs(graph, 0); | ||
} | ||
|
||
|
||
function buildGraph(n, connections) { | ||
const graph = [...Array(n).keys()].reduce((map, i) => { | ||
map.set(i, new Set()); | ||
return map; | ||
}, new Map()); | ||
|
||
connections.forEach(([i, j]) => { | ||
const iAdj = graph.get(i); | ||
iAdj.add(j); | ||
const jAdj = graph.get(j); | ||
jAdj.add(i); | ||
}); | ||
|
||
return graph; | ||
} | ||
|
||
function dfs(graph, current, previous = null, rank = 1, group = []) { | ||
let criticalLinks = []; | ||
group[current] = rank; | ||
|
||
for (const adj of graph.get(current)) { | ||
if (adj === previous) continue; | ||
|
||
if (!group[adj]) { // if not visited (and not in a group yet) | ||
const links = dfs(graph, adj, current, rank + 1, group); | ||
if (links.length) { | ||
criticalLinks = criticalLinks.concat(links); | ||
} | ||
} | ||
|
||
group[current] = Math.min(group[current], group[adj]); | ||
|
||
if (group[adj] >= rank + 1) { | ||
criticalLinks.push([current, adj]); | ||
} | ||
} | ||
|
||
return criticalLinks; | ||
} | ||
|
||
module.exports = criticalConnections; |
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,17 @@ | ||
const assert = require('assert'); | ||
|
||
// const criticalConnections = require('./critical-connections'); | ||
const criticalConnections = require('./critical-connections'); | ||
const data = require('./critical-connections.data'); | ||
|
||
assert.deepEqual(criticalConnections(4, [ | ||
[0, 1], | ||
[1, 2], | ||
[2, 0], | ||
[1, 3], | ||
]), [[1, 3]]); | ||
|
||
const { n, connections } = data.test1000; | ||
assert.deepEqual(criticalConnections(n, connections), []); | ||
|
||
console.log('All tests passed!'); |
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 @@ | ||
// npx jest lab/exercises/10-mixed/critical-connections.spec.js --watch | ||
const criticalConnections = require('./critical-connections'); | ||
|
||
describe('Critical Connections', () => { | ||
it('should work with 4 nodes', () => { | ||
const n = 4; | ||
const connections = [ | ||
[0, 1], | ||
[1, 2], | ||
[2, 0], | ||
[1, 3], | ||
]; | ||
expect(criticalConnections(n, connections)).toEqual([ | ||
[1, 3], | ||
]); | ||
}); | ||
|
||
it('should work with nodes in line (all critical)', () => { | ||
const n = 4; | ||
const connections = [ | ||
[0, 1], | ||
[1, 2], | ||
[2, 3], | ||
]; | ||
expect(criticalConnections(n, connections)).toEqual(expect.arrayContaining([ | ||
[0, 1], | ||
[1, 2], | ||
[2, 3], | ||
])); | ||
}); | ||
|
||
it('should work with nodes in daisy chain (no critical)', () => { | ||
const n = 4; | ||
const connections = [ | ||
[0, 1], | ||
[1, 2], | ||
[2, 3], | ||
[3, 0], | ||
]; | ||
expect(criticalConnections(n, connections)).toEqual(expect.arrayContaining([])); | ||
}); | ||
}); |
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,89 @@ | ||
// npx jest lab/exercises/10-mixed/integer-to-words.spec.js --watch | ||
|
||
const map = { | ||
0: 'Zero', | ||
1: 'One', | ||
2: 'Two', | ||
3: 'Three', | ||
4: 'Four', | ||
5: 'Five', | ||
6: 'Six', | ||
7: 'Seven', | ||
8: 'Eight', | ||
9: 'Nine', | ||
10: 'Ten', | ||
11: 'Eleven', | ||
12: 'Twelve', | ||
13: 'Thirteen', | ||
14: 'Fourteen', | ||
15: 'Fifteen', | ||
16: 'Sixteen', | ||
17: 'Seventeen', | ||
18: 'Eighteen', | ||
19: 'Nineteen', | ||
20: 'Twenty', // Twenty One | ||
|
||
30: 'Thirty', // Thirty Four | ||
40: 'Forty', | ||
50: 'Fifty', | ||
60: 'Sixty', // Sixty Seven | ||
70: 'Seventy', | ||
80: 'Eighty', | ||
90: 'Ninety', | ||
100: 'Hundred', // One Hundred, Two Hundred | ||
|
||
1_000: 'Thousand', // Four Thousand | ||
|
||
1_000_000: 'Million', // One Million | ||
|
||
1_000_000_000: 'Billion', // One Billion | ||
}; | ||
|
||
const keys = [ | ||
// 1_000_000_000, | ||
// 1_000_000, | ||
// 1_000, | ||
// 100, | ||
10, | ||
]; | ||
|
||
/** | ||
* @param {number} num | ||
* @return {string} | ||
* @pomodoro II | ||
*/ | ||
function numberToWords(num) { | ||
if (num < 21) return map[num]; | ||
|
||
let ans = []; | ||
// let i = 0; | ||
|
||
// while (num && i < keys.length) { | ||
// // const div = keys[i++]; // 10 | ||
// const div = 10; | ||
// const reminder = num % div; // 1 | ||
// const left = num - reminder; // 20 | ||
|
||
// if (left && map[left] !== undefined) { | ||
// ans.push(map[left]); | ||
// num -= left; | ||
// } | ||
|
||
// num = reminder; | ||
// } | ||
ans = ans.concat(numberToWords(Math.floor(num/10) * 10)); | ||
ans = ans.concat(numberToWords(Math.floor(num % 10))) | ||
|
||
return ans.join(' '); | ||
}; | ||
|
||
// convert a number into its English representation | ||
|
||
// 21 | ||
// Twenty One | ||
|
||
// 1_234_567_891 | ||
|
||
console.log(process.version); | ||
|
||
module.exports = numberToWords; |
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,12 @@ | ||
/*eslint-disable */ | ||
const assert = require('assert'); | ||
|
||
const numberToWords = require('./integer-to-words'); | ||
|
||
assert.equal(numberToWords(0), 'Zero'); | ||
assert.equal(numberToWords(1), 'One'); | ||
assert.equal(numberToWords(20), 'Twenty'); | ||
assert.equal(numberToWords(21), 'Twenty One'); | ||
assert.equal(numberToWords(99), 'Ninety Nine'); | ||
|
||
console.log('All tests passed!'); |
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,7 @@ | ||
const numberToWords = require('./integer-to-words'); | ||
|
||
describe('Integer to English Words', () => { | ||
it('should convert 0', () => { | ||
expect(numberToWords(0)).toEqual('Zero'); | ||
}); | ||
}); |
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,28 @@ | ||
/** | ||
* Compute how much water it is able to trap after raining. | ||
* @param {number[]} height Non-negative integers representing | ||
* an elevation map where the width of each bar is 1. | ||
* | ||
* @runtime O(n^2) - Brute force | ||
* @space O(1) | ||
*/ | ||
function trap(height) { | ||
let ans = 0; | ||
|
||
for (let i = 0; i < height.length; i++) { | ||
let leftMax = 0; | ||
let rightMax = 0; | ||
for (let j = i; j >= 0; j--) { | ||
leftMax = Math.max(leftMax, height[j]); | ||
} | ||
for (let j = i; j < height.length; j++) { | ||
rightMax = Math.max(rightMax, height[j]); | ||
} | ||
|
||
ans += Math.min(leftMax, rightMax) - height[i]; | ||
} | ||
|
||
return ans; | ||
} | ||
|
||
module.exports = trap; |
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,28 @@ | ||
/** | ||
* Compute how much water it is able to trap after raining. | ||
* @param {number[]} height Non-negative integers representing | ||
* an elevation map where the width of each bar is 1. | ||
* | ||
* @runtime O(n) - using DP | ||
* @space O(n) | ||
*/ | ||
function trap(height) { | ||
let ans = 0; | ||
const leftMax = []; | ||
const rightMax = []; | ||
|
||
for (let j = height.length - 1; j >= 0; j--) { | ||
leftMax[j] = Math.max((leftMax[j + 1] || 0), height[j]); | ||
} | ||
for (let j = 0; j < height.length; j++) { | ||
rightMax[j] = Math.max((rightMax[j - 1] || 0), height[j]); | ||
} | ||
|
||
for (let i = 0; i < height.length; i++) { | ||
ans += Math.min(leftMax[i], rightMax[i]) - height[i]; | ||
} | ||
|
||
return ans; | ||
} | ||
|
||
module.exports = trap; |
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,19 @@ | ||
const trap = require('./trapping-rain-water'); | ||
|
||
describe('Trapping Rain Water', () => { | ||
it('should trap', () => { | ||
expect(trap([1, 0, 1])).toEqual(1); | ||
}); | ||
|
||
it('should not trap', () => { | ||
expect(trap([1, 1, 1])).toEqual(0); | ||
}); | ||
|
||
it('should not trap', () => { | ||
expect(trap([0, 0, 0])).toEqual(0); | ||
}); | ||
|
||
it('should trap', () => { | ||
expect(trap([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1])).toEqual(6); | ||
}); | ||
}); |
Oops, something went wrong.