Skip to content

Commit ae5abc0

Browse files
committed
[Algorithm Design and Techniques]
1 parent c77c903 commit ae5abc0

12 files changed

+333
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export function knapSack(capacity: number, weights: number[], values: number[], n: number): number {
2+
if (n === 0 || capacity === 0) {
3+
return 0;
4+
}
5+
6+
if (weights[n - 1] > capacity) {
7+
return knapSack(capacity, weights, values, n - 1);
8+
} else {
9+
const a: number = values[n - 1] + knapSack(capacity - weights[n - 1], weights, values, n - 1);
10+
const b: number = knapSack(capacity, weights, values, n - 1);
11+
return a > b ? a : b;
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
export function knapSack(capacity: number, weights: number[], values: number[], n: number) {
2+
const kS: Array<Array<number>> = [];
3+
4+
for (let i = 0; i <= n; i++) {
5+
kS[i] = [];
6+
}
7+
8+
for (let i = 0; i <= n; i++) {
9+
for (let w = 0; w <= capacity; w++) {
10+
if (i === 0 || w === 0) {
11+
kS[i][w] = 0;
12+
} else if (weights[i - 1] <= w) {
13+
const a = values[i - 1] + kS[i - 1][w - weights[i - 1]];
14+
const b = kS[i - 1][w];
15+
kS[i][w] = a > b ? a : b; // max(a,b)
16+
console.log(a + ' can be part of the solution');
17+
} else {
18+
kS[i][w] = kS[i - 1][w];
19+
}
20+
}
21+
console.log(kS[i].join());
22+
}
23+
24+
// extra algorithm to find the items that are part of the solution
25+
findValues(n, capacity, kS, values, weights);
26+
27+
return kS[n][capacity];
28+
}
29+
30+
function findValues(
31+
n: number,
32+
capacity: number,
33+
kS: Array<Array<number>>,
34+
weights: number[],
35+
values: number[]
36+
) {
37+
let i = n;
38+
let k = capacity;
39+
40+
console.log('Items that are part of the solution:');
41+
42+
while (i > 0 && k > 0) {
43+
if (kS[i][k] !== kS[i - 1][k]) {
44+
console.log(
45+
'item ' + i + ' can be part of solution w,v: ' + weights[i - 1] + ',' + values[i - 1]
46+
);
47+
i--;
48+
k = k - kS[i][k];
49+
} else {
50+
i--;
51+
}
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
export function lcs(wordX: string, wordY: string) {
2+
const m = wordX.length;
3+
const n = wordY.length;
4+
const l: Array<Array<number>> = [];
5+
const solution: Array<Array<string>> = [];
6+
7+
for (let i = 0; i <= m; i++) {
8+
l[i] = [];
9+
solution[i] = [];
10+
for (let j = 0; j <= n; j++) {
11+
l[i][j] = 0;
12+
solution[i][j] = '0';
13+
}
14+
}
15+
16+
for (let i = 0; i <= m; i++) {
17+
for (let j = 0; j <= n; j++) {
18+
if (i === 0 || j === 0) {
19+
l[i][j] = 0;
20+
} else if (wordX[i - 1] === wordY[j - 1]) {
21+
l[i][j] = l[i - 1][j - 1] + 1;
22+
solution[i][j] = 'diagonal';
23+
} else {
24+
const a = l[i - 1][j];
25+
const b = l[i][j - 1];
26+
l[i][j] = a > b ? a : b; // max(a,b)
27+
solution[i][j] = l[i][j] === l[i - 1][j] ? 'top' : 'left';
28+
}
29+
}
30+
console.log(l[i].join());
31+
console.log(solution[i].join());
32+
}
33+
34+
printSolution(solution, wordX, m, n);
35+
36+
return l[m][n];
37+
}
38+
39+
function printSolution(solution: Array<Array<string>>, wordX: string, m: number, n: number) {
40+
let a = m;
41+
let b = n;
42+
let x = solution[a][b];
43+
let answer = '';
44+
45+
while (x !== '0') {
46+
if (solution[a][b] === 'diagonal') {
47+
answer = wordX[a - 1] + answer;
48+
a--;
49+
b--;
50+
} else if (solution[a][b] === 'left') {
51+
b--;
52+
} else if (solution[a][b] === 'top') {
53+
a--;
54+
}
55+
x = solution[a][b];
56+
}
57+
58+
console.log('lcs: ' + answer);
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
export function lcs(wordX: string, wordY: string) {
2+
const m = wordX.length;
3+
const n = wordY.length;
4+
const l: Array<Array<number>> = [];
5+
6+
for (let i = 0; i <= m; i++) {
7+
l[i] = [];
8+
for (let j = 0; j <= n; j++) {
9+
l[i][j] = 0;
10+
}
11+
}
12+
13+
for (let i = 0; i <= m; i++) {
14+
for (let j = 0; j <= n; j++) {
15+
if (i === 0 || j === 0) {
16+
l[i][j] = 0;
17+
} else if (wordX[i - 1] === wordY[j - 1]) {
18+
l[i][j] = l[i - 1][j - 1] + 1;
19+
} else {
20+
const a = l[i - 1][j];
21+
const b = l[i][j - 1];
22+
l[i][j] = a > b ? a : b; // max(a,b)
23+
}
24+
}
25+
console.log(l[i].join());
26+
}
27+
28+
return l[m][n];
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
export function matrixChainOrder(p: number[]): number {
2+
const n = p.length;
3+
4+
const m: Array<Array<number>> = [];
5+
const s: Array<Array<number>> = [];
6+
7+
for (let i = 1; i <= n; i++) {
8+
m[i] = [];
9+
m[i][i] = 0;
10+
}
11+
12+
for (let i = 0; i <= n; i++) {
13+
// to help printing the optimal solution
14+
s[i] = []; // auxiliary
15+
for (let j = 0; j <= n; j++) {
16+
s[i][j] = 0;
17+
}
18+
}
19+
20+
for (let l = 2; l < n; l++) {
21+
for (let i = 1; i <= n - l + 1; i++) {
22+
const j = i + l - 1;
23+
m[i][j] = Number.MAX_SAFE_INTEGER;
24+
for (let k = i; k <= j - 1; k++) {
25+
// q = cost/scalar multiplications
26+
const q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
27+
if (q < m[i][j]) {
28+
m[i][j] = q;
29+
s[i][j] = k; // s[i,j] = Second auxiliary table that stores k
30+
}
31+
}
32+
}
33+
}
34+
35+
console.log(m);
36+
console.log(s);
37+
38+
printOptimalParenthesis(s, 1, n - 1);
39+
40+
return m[1][n - 1];
41+
}
42+
43+
function printOptimalParenthesis(s: Array<Array<number>>, i: number, j: number) {
44+
if (i === j) {
45+
console.log('A[' + i + ']');
46+
} else {
47+
console.log('(');
48+
printOptimalParenthesis(s, i, s[i][j]);
49+
printOptimalParenthesis(s, s[i][j] + 1, j);
50+
console.log(')');
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
export function minCoinChange(coins: number[], amount: number) {
2+
const cache: Array<Array<number>> = [];
3+
4+
// tslint:disable-next-line:no-shadowed-variable
5+
const makeChange = function(amount: number) {
6+
if (!amount) {
7+
return [];
8+
}
9+
if (cache[amount]) {
10+
return cache[amount];
11+
}
12+
let min: number[] = [],
13+
newMin,
14+
newAmount;
15+
for (let i = 0; i < coins.length; i++) {
16+
const coin = coins[i];
17+
newAmount = amount - coin;
18+
if (newAmount >= 0) {
19+
newMin = makeChange(newAmount);
20+
}
21+
if (
22+
newAmount >= 0 &&
23+
(newMin.length < min.length - 1 || !min.length) &&
24+
(newMin.length || !newAmount)
25+
) {
26+
min = [coin].concat(newMin);
27+
console.log('new Min ' + min + ' for ' + amount);
28+
}
29+
}
30+
return (cache[amount] = min);
31+
};
32+
33+
return makeChange(amount);
34+
}

src/ts/algorithms/greedy/knapsack.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
function knapSack(capacity: number, weights: number[], values: number[]) {
2+
const n = values.length;
3+
let load = 0;
4+
let val = 0;
5+
6+
for (let i = 0; i < n && load < capacity; i++) {
7+
if (weights[i] <= capacity - load) {
8+
val += values[i];
9+
load += weights[i];
10+
console.log('using item ' + (i + 1) + ' for the solution');
11+
} else {
12+
const r = (capacity - load) / weights[i];
13+
val += r * values[i];
14+
load += weights[i];
15+
console.log('using ratio of ' + r + ' for item ' + (i + 1) + ' for the solution');
16+
}
17+
}
18+
return val;
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
function lcs(wordX: string, wordY: string, m = wordX.length, n = wordY.length): number {
2+
if (m === 0 || n === 0) {
3+
return 0;
4+
}
5+
6+
if (wordX[m - 1] === wordY[n - 1]) {
7+
return 1 + lcs(wordX, wordY, m - 1, n - 1);
8+
} else {
9+
const a = lcs(wordX, wordY, m, n - 1);
10+
const b = lcs(wordX, wordY, m - 1, n);
11+
return a > b ? a : b;
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export function matrixChainOrder(p: number[], i = 1, j = p.length - 1): number {
2+
if (i === j) {
3+
return 0;
4+
}
5+
6+
let min = Number.MAX_SAFE_INTEGER;
7+
8+
for (let k = i; k < j; k++) {
9+
const count =
10+
matrixChainOrder(p, i, k) + matrixChainOrder(p, k + 1, j) + p[i - 1] * p[k] * p[j];
11+
12+
if (count < min) {
13+
min = count;
14+
}
15+
}
16+
17+
return min;
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function minCoinChange(coins: number[], amount: number) {
2+
const change: number[] = [];
3+
let total = 0;
4+
for (let i = coins.length; i >= 0; i--) {
5+
const coin = coins[i];
6+
while (total + coin <= amount) {
7+
change.push(coin);
8+
total += coin;
9+
}
10+
}
11+
return change;
12+
}

src/ts/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export { findMinValue as findMinValue } from './algorithms/search/min-max-search
6262

6363
// chapter 14
6464
export { binarySearch as binarySearchRecursive } from './algorithms/search/binary-search-recursive';
65+
export { minCoinChange as minCoinChange } from './algorithms/dynamic-programing/min-coin-change';
6566

6667

6768
/* import { hotPotato } from './others/hot-potato';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import 'mocha';
2+
import { expect } from 'chai';
3+
import { minCoinChange } from '../../../../src/ts/index';
4+
5+
describe('Dynamic Programming: Min Coin Change', () => {
6+
7+
it('works with amount 0', () => {
8+
expect(minCoinChange([1, 2, 3], 0)).to.deep.equal([]);
9+
});
10+
11+
it('works with amount 1', () => {
12+
expect(minCoinChange([1, 2, 3], 1)).to.deep.equal([1]);
13+
});
14+
15+
it('works with amount 2', () => {
16+
expect(minCoinChange([1, 2, 3], 2)).to.deep.equal([2]);
17+
});
18+
19+
it('works with amount 3', () => {
20+
expect(minCoinChange([1, 2, 3], 3)).to.deep.equal([3]);
21+
});
22+
23+
it('works with amount 4', () => {
24+
expect(minCoinChange([1, 2, 3], 4)).to.deep.equal([1, 3]);
25+
});
26+
27+
it('works with amount 6', () => {
28+
expect(minCoinChange([1, 2, 3], 6)).to.deep.equal([3, 3]);
29+
});
30+
});

0 commit comments

Comments
 (0)