reorg and add code for second edition
This commit is contained in:
78
11_dynamic_programming/ES6/01_longest_common_subsequence.js
Normal file
78
11_dynamic_programming/ES6/01_longest_common_subsequence.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Create a matrix
|
||||
* @param {number} rows Number of rows
|
||||
* @param {number} columns ANumber of columns
|
||||
* @returns {Array} Matrix
|
||||
*/
|
||||
const createMatrix = (rows = 0, columns = 0) => {
|
||||
const matrix = [];
|
||||
|
||||
for (let i = 0; i < rows; i++) {
|
||||
matrix[i] = Array(columns).fill(0);
|
||||
}
|
||||
|
||||
return matrix;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the longest substring
|
||||
* @param {string} firstWord First word
|
||||
* @param {string} secondWord Second word
|
||||
* @returns {string} The longest substring
|
||||
*/
|
||||
const longestSubstring = (firstWord = "", secondWord = "") => {
|
||||
const matrix = JSON.parse(
|
||||
JSON.stringify(createMatrix(firstWord.length, secondWord.length))
|
||||
);
|
||||
let sizeSequence = 0;
|
||||
let indexSequence = 0;
|
||||
|
||||
for (let i = 0; i < firstWord.length; i++) {
|
||||
for (let j = 0; j < secondWord.length; j++) {
|
||||
if (firstWord[i] === secondWord[j]) {
|
||||
matrix[i][j] = (i && j) > 0 ? matrix[i - 1][j - 1] + 1 : 1;
|
||||
|
||||
if (matrix[i][j] >= sizeSequence) {
|
||||
sizeSequence = matrix[i][j];
|
||||
indexSequence = i + 1;
|
||||
}
|
||||
} else {
|
||||
matrix[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return firstWord.slice(indexSequence - sizeSequence, indexSequence);
|
||||
};
|
||||
|
||||
longestSubstring("vista", "hish"); // "is"
|
||||
longestSubstring("fish", "hish"); // "ish"
|
||||
|
||||
/**
|
||||
* Find the longest common subsequence
|
||||
* @param {string} firstWord First word
|
||||
* @param {string} secondWord Second word
|
||||
* @returns {number} The longest common subsequence
|
||||
*/
|
||||
const longestCommonSubsequence = (firstWord = "", secondWord = "") => {
|
||||
const matrix = JSON.parse(
|
||||
JSON.stringify(createMatrix(firstWord.length, secondWord.length))
|
||||
);
|
||||
if (matrix.length === 0 || matrix[0].length === 0) return 0;
|
||||
for (let i = 0; i < firstWord.length; i++) {
|
||||
for (let j = 0; j < secondWord.length; j++) {
|
||||
if (firstWord[i] === secondWord[j]) {
|
||||
matrix[i][j] = (i && j) > 0 ? matrix[i - 1][j - 1] + 1 : 1;
|
||||
} else {
|
||||
matrix[i][j] = Math.max(
|
||||
i > 0 ? matrix[i - 1][j] : 0,
|
||||
j > 0 ? matrix[i][j - 1] : 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return matrix[firstWord.length - 1][secondWord.length - 1];
|
||||
};
|
||||
|
||||
longestCommonSubsequence("fish", "fosh"); // 3
|
||||
longestCommonSubsequence("fort", "fosh"); // 2
|
||||
27
11_dynamic_programming/Haskell/01_knapsack-powerset.hs
Normal file
27
11_dynamic_programming/Haskell/01_knapsack-powerset.hs
Normal file
@@ -0,0 +1,27 @@
|
||||
import Control.Applicative
|
||||
import Data.List
|
||||
import qualified Data.Set as Set
|
||||
import qualified Data.HashMap.Strict as Map
|
||||
|
||||
items = Map.fromList [
|
||||
("stereo", (4, 3000)),
|
||||
("laptop", (3, 2000)),
|
||||
("guitar", (1, 1500))
|
||||
]
|
||||
|
||||
value set = (a, b)
|
||||
where
|
||||
weightandvalues = (sequence $ map (`Map.lookup` items) set)
|
||||
Just (a,b) = Just (foldl (\(a,b) (c,d) -> (a+c, b+d)) (0,0)) <*> weightandvalues
|
||||
|
||||
powerSet xs = foldl (\acc x -> acc ++ (map (\e -> x:e) acc)) [[]] xs
|
||||
|
||||
solution = foldl
|
||||
(\acc v -> let
|
||||
(firstweight, firstvalue) = value acc
|
||||
(secondweight, secondvalue) = value v
|
||||
in if firstweight <= 4 && firstvalue >= secondvalue then acc else if secondweight <= 4 then v else acc)
|
||||
first
|
||||
rest
|
||||
where
|
||||
(first: rest) = filter (not . null) $ powerSet $ (Map.keys items)
|
||||
62
11_dynamic_programming/Haskell/01_knapsack_dynamic_prog.hs
Normal file
62
11_dynamic_programming/Haskell/01_knapsack_dynamic_prog.hs
Normal file
@@ -0,0 +1,62 @@
|
||||
import qualified Data.HashMap.Strict as Map
|
||||
import Data.Array
|
||||
|
||||
type Grid = Array (Integer, Integer) (Integer, [Char])
|
||||
|
||||
itemsMap = Map.fromList [
|
||||
("stereo", (4, 3000)),
|
||||
("laptop", (3, 2000)),
|
||||
("guitar", (1, 1500)),
|
||||
("iphone", (1, 2000))
|
||||
]
|
||||
|
||||
weightOf item = case Map.lookup item itemsMap of
|
||||
Just (w, v) -> w
|
||||
otherwise -> 0
|
||||
|
||||
valueOf item = case Map.lookup item itemsMap of
|
||||
Just (w, v) -> v
|
||||
otherwise -> 0
|
||||
|
||||
emptyGrid :: Grid
|
||||
emptyGrid = array ((0,0), (3,4)) [((x,y), (0, "")) | x <- [0..3], y <- [0..4]]
|
||||
|
||||
best :: Grid -> Integer -> Integer -> String -> (Integer, String)
|
||||
best arr row col item =
|
||||
let weight = weightOf item
|
||||
value = valueOf item
|
||||
(previousMax, previousItems) = if (row /= 0) then arr ! (row - 1, col) else (0, "")
|
||||
(valueOfRemainingSpace, itemsInRemainingSpace) =
|
||||
if (row /= 0 && (col - weight) >= 0)
|
||||
then arr ! (row - 1, col - weight)
|
||||
else (0, "")
|
||||
in if (previousMax > (value + valueOfRemainingSpace))
|
||||
then arr ! (row - 1, col)
|
||||
else (value + valueOfRemainingSpace, itemsInRemainingSpace ++ " " ++ item)
|
||||
|
||||
fillPrevBest arr row col =
|
||||
if row /= 0 then (//) arr [((row, col), arr ! (row - 1, col))] else arr
|
||||
|
||||
fillGrid emptyGrid = foldl
|
||||
(\acc pair ->
|
||||
let row = fst pair
|
||||
item = snd pair
|
||||
(weight, value) = (weightOf item, valueOf item)
|
||||
in foldl
|
||||
(\arr col ->
|
||||
case weight <= col of
|
||||
True -> (//) arr [((row, col), best arr row col item)]
|
||||
False -> fillPrevBest arr row col
|
||||
)
|
||||
acc
|
||||
[0..4]
|
||||
)
|
||||
emptyGrid
|
||||
items
|
||||
where items = zip [0..3] $ Map.keys itemsMap
|
||||
|
||||
solution = foldl
|
||||
(\(x, a) (y, b) -> if x > y then (x, a) else (y, b))
|
||||
first
|
||||
rest
|
||||
where (first: rest) = elems $ fillGrid emptyGrid
|
||||
@@ -0,0 +1,32 @@
|
||||
$word_a = "fish"
|
||||
$word_b = "vista"
|
||||
|
||||
# Init the empty two-dimensional array
|
||||
$cell = @()
|
||||
for ($i = 0; $i -lt $word_a.Length; $i++)
|
||||
{
|
||||
$list = @()
|
||||
for ($j = 0; $j -lt $word_b.Length; $j++)
|
||||
{
|
||||
$list += , 0
|
||||
}
|
||||
$cell += , $list
|
||||
}
|
||||
|
||||
for ($i = 0; $i -lt $word_a.Length; $i++)
|
||||
{
|
||||
for ($j = 0; $j -lt $word_b.Length; $j++)
|
||||
{
|
||||
if ($word_a[$i] -eq $word_b[$j]) {
|
||||
# The letters match.
|
||||
$cell[$i][$j] = $cell[$i-1][$j-1] + 1
|
||||
}
|
||||
else
|
||||
{
|
||||
# The letters don't match.
|
||||
$cell[$i][$j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0..($cell.count-1) | ForEach-Object {Write-Host $cell[$_] -Separator `t}
|
||||
2
11_dynamic_programming/csharp/01_longest_common_subsequence/.gitignore
vendored
Normal file
2
11_dynamic_programming/csharp/01_longest_common_subsequence/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
**/bin/*
|
||||
**/obj/*
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
|
||||
namespace ConsoleApplication
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var result = LongestCommonSubsequence("fish", "vistafh");
|
||||
Console.WriteLine($"{result.Item1}: {result.Item2}"); // ish: 3
|
||||
}
|
||||
|
||||
public static (string, int) LongestCommonSubsequence(string word1, string word2)
|
||||
{
|
||||
if (string.IsNullOrEmpty(word1) || string.IsNullOrEmpty(word2))
|
||||
return ("", 0);
|
||||
|
||||
string subSeq;
|
||||
var matrix = new int[word1.Length + 1, word2.Length + 1];
|
||||
|
||||
for (int i = 1; i <= word1.Length; i++)
|
||||
{
|
||||
for (int j = 1; j <= word2.Length; j++)
|
||||
{
|
||||
if (word1[i - 1] == word2[j - 1])
|
||||
{
|
||||
matrix[i, j] = matrix[i - 1, j - 1] + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix[i, j] = Math.Max(matrix[i, j - 1], matrix[i - 1, j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subSeq = Read(matrix, word1, word2);
|
||||
|
||||
return (subSeq, subSeq.Length);
|
||||
}
|
||||
|
||||
private static string Read(int[,] matrix, string word1, string word2)
|
||||
{
|
||||
string subSeq = null;
|
||||
int x = word1.Length;
|
||||
int y = word2.Length;
|
||||
|
||||
while (x > 0 && y > 0)
|
||||
{
|
||||
if (word1[x - 1] == word2[y - 1])
|
||||
{
|
||||
subSeq += word1[x - 1];
|
||||
x--;
|
||||
y--;
|
||||
}
|
||||
else if (matrix[x - 1, y] > matrix[x, y - 1])
|
||||
{
|
||||
x--;
|
||||
}
|
||||
else
|
||||
{
|
||||
y--;
|
||||
}
|
||||
}
|
||||
|
||||
var charArray = subSeq.ToCharArray();
|
||||
Array.Reverse(charArray);
|
||||
subSeq = new string(charArray);
|
||||
|
||||
return subSeq;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"buildOptions": {
|
||||
"debugType": "portable",
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"type": "platform",
|
||||
"version": "1.0.1"
|
||||
}
|
||||
},
|
||||
"imports": "dnxcore50"
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
46
11_dynamic_programming/csharp/02_levenshtein/Program.cs
Normal file
46
11_dynamic_programming/csharp/02_levenshtein/Program.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
|
||||
namespace ConsoleApplication
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static int LevenshteinDistance(string source, string target)
|
||||
{
|
||||
var matrix = CreateMatrix(source, target);
|
||||
|
||||
for (int i = 1; i <= source.Length; i++)
|
||||
{
|
||||
for (int j = 1; j <= target.Length; j++)
|
||||
{
|
||||
matrix[i, j] = Math.Min(matrix[i, j - 1] + 1, Math.Min(
|
||||
matrix[i - 1, j] + 1,
|
||||
matrix[i - 1, j - 1] + (source[i - 1] != target[j - 1] ? 1 : 0)));
|
||||
}
|
||||
}
|
||||
|
||||
return matrix[source.Length, target.Length];
|
||||
}
|
||||
|
||||
private static int[,] CreateMatrix(string source, string target)
|
||||
{
|
||||
var matrix = new int[source.Length + 1, target.Length + 1];
|
||||
|
||||
if (source.Length < target.Length)
|
||||
{
|
||||
(source, target) = (target, source);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= source.Length; i++)
|
||||
{
|
||||
matrix[i, 0] = i;
|
||||
|
||||
if (i <= target.Length)
|
||||
{
|
||||
matrix[0, i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
void main(List<String> args) {
|
||||
final table = longestCommonSubsequence('blue', 'clues');
|
||||
|
||||
for (List<int> element in table) {
|
||||
print(element);
|
||||
}
|
||||
}
|
||||
|
||||
List<List<int>> longestCommonSubsequence(String word1, String word2) {
|
||||
final tableWord1 = word1.split('');
|
||||
final tableWord2 = word2.split('');
|
||||
final table = List.generate(
|
||||
tableWord2.length, (index) => List<int>.filled(tableWord1.length, 0));
|
||||
|
||||
for (int i = 0; i < tableWord1.length; i++) {
|
||||
for (int j = 0; j < tableWord2.length; j++) {
|
||||
if (tableWord2[j] == tableWord1[i]) {
|
||||
table[j][i] = (j - 1 >= 0 && i - 1 >= 0) ? table[j - 1][i - 1] + 1 : 1;
|
||||
} else {
|
||||
final top = (j - 1 >= 0) ? table[j - 1][i] : 0;
|
||||
final left = (i - 1 >= 0) ? table[j][i - 1] : 0;
|
||||
table[j][i] = (top > left) ? top : left;
|
||||
}
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
25
11_dynamic_programming/dart/02_longest_common_substring.dart
Normal file
25
11_dynamic_programming/dart/02_longest_common_substring.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
void main(List<String> args) {
|
||||
final table = longestCommonSubstring('fish', 'hish');
|
||||
|
||||
for (List<int> element in table) {
|
||||
print(element);
|
||||
}
|
||||
}
|
||||
|
||||
List<List<int>> longestCommonSubstring(String word1, String word2) {
|
||||
final tableWord1 = word1.split('');
|
||||
final tableWord2 = word2.split('');
|
||||
final table = List.generate(
|
||||
tableWord2.length, (index) => List<int>.filled(tableWord1.length, 0));
|
||||
|
||||
for (int i = 0; i < tableWord1.length; i++) {
|
||||
for (int j = 0; j < tableWord2.length; j++) {
|
||||
if (tableWord2[j] == tableWord1[i]) {
|
||||
table[j][i] = table[j - 1][j - 1] + 1;
|
||||
} else {
|
||||
table[j][i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# `cell` is a map of maps here, e.g.
|
||||
# cell = %{
|
||||
# 0 => %{0 => 0, ...},
|
||||
# 1 => %{...},
|
||||
# ...
|
||||
# }
|
||||
|
||||
if String.at(word_a, i) == String.at(word_a, j) do
|
||||
put_in(cell[i - 1][j - 1], cell[i - 1][j - 1] + 1)
|
||||
else
|
||||
put_in(cell[i - 1][j - 1], max(cell[i - 1][j], cell[i][j - 1]))
|
||||
end
|
||||
@@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
func createMatrix(rows, cols int) [][]int {
|
||||
cell := make([][]int, rows)
|
||||
for i := range cell {
|
||||
cell[i] = make([]int, cols)
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
func substring(a, b string) string {
|
||||
lcs := 0
|
||||
lastSubIndex := 0
|
||||
cell := createMatrix(len(a)+1, len(b)+1)
|
||||
|
||||
for i := 1; i <= len(a); i++ {
|
||||
for j := 1; j <= len(b); j++ {
|
||||
if a[i-1] == b[j-1] {
|
||||
cell[i][j] = cell[i-1][j-1] + 1
|
||||
|
||||
if cell[i][j] > lcs {
|
||||
lcs = cell[i][j]
|
||||
lastSubIndex = i
|
||||
}
|
||||
} else {
|
||||
cell[i][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return a[lastSubIndex-lcs : lastSubIndex]
|
||||
}
|
||||
|
||||
func subsequence(a, b string) int {
|
||||
cell := createMatrix(len(a)+1, len(b)+1)
|
||||
|
||||
for i := 1; i <= len(a); i++ {
|
||||
for j := 1; j <= len(b); j++ {
|
||||
if a[i-1] == b[j-1] {
|
||||
cell[i][j] = cell[i-1][j-1] + 1
|
||||
} else {
|
||||
cell[i][j] = cell[i-1][j]
|
||||
|
||||
if cell[i][j] < cell[i][j-1] {
|
||||
cell[i][j] = cell[i][j-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cell[len(a)][len(b)]
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSubstring(t *testing.T) {
|
||||
var stests = []struct {
|
||||
name, a, b, expected string
|
||||
}{
|
||||
{"hish-vista", "vista", "hish", "is"},
|
||||
{"hish-fish", "fish", "hish", "ish"},
|
||||
}
|
||||
|
||||
for _, tt := range stests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := substring(tt.a, tt.b)
|
||||
|
||||
if actual != tt.expected {
|
||||
t.Errorf("Expected %s but received %s", tt.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubsequence(t *testing.T) {
|
||||
var stests = []struct {
|
||||
name, a, b string
|
||||
expected int
|
||||
}{
|
||||
{"fosh-fish", "fish", "fosh", 3},
|
||||
{"fosh-fort", "fort", "fosh", 2},
|
||||
}
|
||||
|
||||
for _, tt := range stests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := subsequence(tt.a, tt.b)
|
||||
|
||||
if actual != tt.expected {
|
||||
t.Errorf("Expected %d but received %d", tt.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import java.util.Arrays;
|
||||
|
||||
public class LongestCommonSubsequence {
|
||||
public static void main(String[] args) {
|
||||
// if (word_a[i] == word_b[j]) {
|
||||
// cell[i][j] = cell[i - 1][j - 1] + 1;
|
||||
// } else {
|
||||
// cell[i][j] = Math.Max(cell[i - 1][j], cell[i][j - 1]);
|
||||
// }
|
||||
|
||||
String wordA = "hish";
|
||||
String wordB = "fish";
|
||||
|
||||
int[][] cell = new int[wordA.length()][wordB.length()];
|
||||
|
||||
for (int i = 0; i < wordA.length(); i++) {
|
||||
for (int j = 0; j < wordB.length(); j++) {
|
||||
// The letters match
|
||||
if (wordA.charAt(i) == wordB.charAt(j)) {
|
||||
if (i > 0 && j > 0) {
|
||||
cell[i][j] = cell[i - 1][j - 1] + 1;
|
||||
} else {
|
||||
cell[i][j] = 1;
|
||||
}
|
||||
} else {
|
||||
// The letters don't match.
|
||||
if (i == 0 && j > 0) {
|
||||
cell[i][j] = cell[i][j - 1];
|
||||
} else if (i > 0 && j == 0) {
|
||||
cell[i][j] = cell[i - 1][j];
|
||||
} else if (i > 0 && j > 0) {
|
||||
cell[i][j] = Math.max(cell[i - 1][j], cell[i][j - 1]);
|
||||
} else {
|
||||
cell[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printResult(cell);
|
||||
// [0, 0, 0, 1]
|
||||
// [0, 1, 1, 1]
|
||||
// [0, 1, 2, 2]
|
||||
// [0, 1, 2, 3]
|
||||
|
||||
}
|
||||
|
||||
private static void printResult(int[][] arr) {
|
||||
for (int[] row : arr) {
|
||||
System.out.println(Arrays.toString(row));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Search for LCS
|
||||
*
|
||||
* @param {string} string1 first string
|
||||
* @param {string} string2 second string
|
||||
*
|
||||
* @return {object} with keys: lcs, offset, sequence
|
||||
*/
|
||||
function lcs(string1, string2) {
|
||||
if (!string1 || !string2) {
|
||||
return {
|
||||
lcs: 0,
|
||||
offset: 0,
|
||||
sequence: ""
|
||||
};
|
||||
}
|
||||
|
||||
let lcs = 0;
|
||||
|
||||
let lastSubIndex = 0;
|
||||
|
||||
let table = [];
|
||||
let len1 = string1.length;
|
||||
let len2 = string2.length;
|
||||
let row;
|
||||
let col;
|
||||
|
||||
/**
|
||||
* Matrix
|
||||
* - has an increased dimension to avoid extra checks for previous elements
|
||||
*
|
||||
* - the number of rows is equal to the length of the first string + 1
|
||||
* - the number of columns is equal to the length of the second string + 1
|
||||
*/
|
||||
for (row = 0; row <= len1; row++) {
|
||||
table[row] = [];
|
||||
for (col = 0; col <= len2; col++) {
|
||||
table[row][col] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the matrix
|
||||
let i;
|
||||
let j;
|
||||
|
||||
for (i = 0; i < len1; i++) {
|
||||
for (j = 0; j < len2; j++) {
|
||||
if (string1[i] === string2[j]) {
|
||||
// The letters match
|
||||
if (table[i][j] === 0) {
|
||||
table[i + 1][j + 1] = 1;
|
||||
} else {
|
||||
table[i + 1][j + 1] = table[i][j] + 1;
|
||||
}
|
||||
|
||||
// increment lcs if it's needed
|
||||
if (table[i + 1][j + 1] > lcs) {
|
||||
lcs = table[i + 1][j + 1];
|
||||
lastSubIndex = i;
|
||||
}
|
||||
} else {
|
||||
// The letters don't match
|
||||
table[i + 1][j + 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
lcs: lcs,
|
||||
offset: lastSubIndex - lcs + 1,
|
||||
sequence: string1.slice(lastSubIndex - lcs + 1, lastSubIndex + 1)
|
||||
};
|
||||
}
|
||||
|
||||
console.log(lcs("hish", "fish")); // { lcs: 3, offset: 1, sequence: 'ish' }
|
||||
console.log(lcs("vista", "hish")); // { lcs: 2, offset: 1, sequence: 'is' }
|
||||
console.log(lcs("google", "abcdefgooglehijklm")); // { lcs: 6, offset: 0, sequence: 'google' }
|
||||
console.log(lcs("0", 0)); // { lcs: 0, offset: 0, sequence: '' }
|
||||
47
11_dynamic_programming/javascript/02_levenstein.js
Normal file
47
11_dynamic_programming/javascript/02_levenstein.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Compute the edit distance between the two given strings
|
||||
*
|
||||
* @param {*} source
|
||||
* @param {*} target
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
function getEditDistance(source, target) {
|
||||
if (source.length == 0) return target.length;
|
||||
if (target.length == 0) return source.length;
|
||||
|
||||
let i;
|
||||
let j;
|
||||
let matrix = [];
|
||||
|
||||
// Fill the column
|
||||
for (i = 0; i <= target.length; i++) {
|
||||
matrix[i] = [i];
|
||||
}
|
||||
|
||||
// Fill the column
|
||||
for (j = 0; j <= source.length; j++) {
|
||||
matrix[0][j] = j;
|
||||
}
|
||||
|
||||
// Fill in the rest of the matrix
|
||||
for (i = 1; i <= target.length; i++) {
|
||||
for (j = 1; j <= source.length; j++) {
|
||||
if (target.charAt(i - 1) == source.charAt(j - 1)) {
|
||||
matrix[i][j] = matrix[i - 1][j - 1];
|
||||
} else {
|
||||
matrix[i][j] = Math.min(
|
||||
matrix[i - 1][j - 1] + 1, // substitution
|
||||
Math.min(
|
||||
matrix[i][j - 1] + 1, // insertion
|
||||
matrix[i - 1][j] + 1
|
||||
)
|
||||
); // deletion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matrix[target.length][source.length];
|
||||
}
|
||||
|
||||
console.log(getEditDistance("google", "notgoogl")); // 4
|
||||
7
11_dynamic_programming/javascript/examples/base.js
Normal file
7
11_dynamic_programming/javascript/examples/base.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = function initialize_matrix(rows, cols) {
|
||||
let matrix = [];
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
matrix.push(Array(cols.length).fill(0));
|
||||
}
|
||||
return matrix;
|
||||
};
|
||||
25
11_dynamic_programming/javascript/examples/diff_two_words.js
Normal file
25
11_dynamic_programming/javascript/examples/diff_two_words.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const initialize_matrix = require("./base.js");
|
||||
|
||||
function diff(firstWord, secondWord) {
|
||||
let arr1 = firstWord.split("");
|
||||
let arr2 = secondWord.split("");
|
||||
let matrix = initialize_matrix(arr1, arr2);
|
||||
for (let i = 0; i < arr1.length; i++) {
|
||||
for (let j = 0; j < arr2.length; j++) {
|
||||
if (arr1[i] == arr2[j]) {
|
||||
if (i > 0 && j > 0) {
|
||||
matrix[i][j] = matrix[i - 1][j - 1] + 1;
|
||||
} else {
|
||||
matrix[i][j] = 1;
|
||||
}
|
||||
} else {
|
||||
if (i > 0 && j > 0) {
|
||||
matrix[i][j] = Math.max(matrix[i - 1][j], matrix[i][j - 1]);
|
||||
} else {
|
||||
matrix[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return matrix[arr1.length - 1][arr2.length - 1];
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
if word_a[i] == word_b[j] then
|
||||
-- The letters match.
|
||||
cell[i][j] = cell[i - 1][j - 1] + 1
|
||||
else
|
||||
-- The letters don't match.
|
||||
cell[i][j] = math.max(cell[i - 1][j], cell[i][j - 1])
|
||||
end
|
||||
45
11_dynamic_programming/php/01_longest_common_subsequence.php
Normal file
45
11_dynamic_programming/php/01_longest_common_subsequence.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @param string $stringA
|
||||
* @param string $stringB
|
||||
* @return array
|
||||
*/
|
||||
function search(string $stringA, string $stringB): array
|
||||
{
|
||||
$cell = [];
|
||||
|
||||
for ($i = 0; $i < strlen($stringA); $i++) {
|
||||
for ($j = 0; $j < strlen($stringB); $j++) {
|
||||
if ($stringA[$i] === $stringB[$j]) {
|
||||
if (isset($cell[$i - 1][$j - 1])) {
|
||||
$cell[$i][$j] = $cell[$i - 1][$j - 1] + 1;
|
||||
} else {
|
||||
$cell[$i][$j] = 1;
|
||||
}
|
||||
} else {
|
||||
if (isset($cell[$i - 1][$j]) || isset($cell[$i][$j - 1])) {
|
||||
$cell[$i][$j] = max(
|
||||
isset($cell[$i - 1][$j]) ? $cell[$i - 1][$j] : 0,
|
||||
isset($cell[$i][$j - 1]) ? $cell[$i][$j - 1] : 0
|
||||
);
|
||||
} else {
|
||||
$cell[$i][$j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $cell;
|
||||
}
|
||||
|
||||
print_r(search('fish', 'fosh'));
|
||||
|
||||
/*
|
||||
[ f o s h
|
||||
f [1,1,1,1],
|
||||
i [1,1,1,1],
|
||||
s [1,1,2,2],
|
||||
h [1,1,2,3]
|
||||
]
|
||||
*/
|
||||
@@ -0,0 +1,13 @@
|
||||
dp_table_blue = ["b", "l", "u", "e"]
|
||||
dp_table_clues = ["c", "l", "u", "e", "s"]
|
||||
dp_table = [[0 for i in range(len(dp_table_blue))] for i in range(len(dp_table_clues))] # (5,4)
|
||||
print(dp_table)
|
||||
|
||||
for i in range(0, len(dp_table_blue)):
|
||||
for j in range(0, len(dp_table_clues)):
|
||||
if dp_table_clues[j] == dp_table_blue[i]:
|
||||
dp_table[j][i] = dp_table[j-1][i-1] + 1
|
||||
else:
|
||||
dp_table[j][i] = max(dp_table[j-1][i], dp_table[j][i-1])
|
||||
|
||||
print(dp_table)
|
||||
13
11_dynamic_programming/python/02_longest_common_substring.py
Normal file
13
11_dynamic_programming/python/02_longest_common_substring.py
Normal file
@@ -0,0 +1,13 @@
|
||||
dp_table_blue = ["b", "l", "u", "e"]
|
||||
dp_table_clues = ["c", "l", "u", "e", "s"]
|
||||
dp_table = [[0 for i in range(len(dp_table_blue))] for i in range(len(dp_table_clues))] # (5,4)
|
||||
print(dp_table)
|
||||
|
||||
for i in range(0, len(dp_table_blue)):
|
||||
for j in range(0, len(dp_table_clues)):
|
||||
if dp_table_clues[j] == dp_table_blue[i]:
|
||||
dp_table[i][j] = dp_table[i-1][i-1] + 1
|
||||
else:
|
||||
dp_table[i][j] = 0
|
||||
|
||||
print(dp_table)
|
||||
@@ -0,0 +1,7 @@
|
||||
if word_a[i] == word_b[j]
|
||||
# The letters match.
|
||||
cell[i][j] = cell[i-1][j-1] + 1
|
||||
else
|
||||
# The letters don't match.
|
||||
cell[i][j] = [cell[i-1][j], cell[i][j-1]].max
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
import Foundation
|
||||
|
||||
if wordA[i] == wordB[j] {
|
||||
// The letters match
|
||||
cell[i][j] = cell[i-1][j-1] + 1
|
||||
} else {
|
||||
// The letters don't match.
|
||||
cell[i][j] = max(cell[i-1][j], cell[i][j-1])
|
||||
}
|
||||
|
||||
/* Working example for "play" with
|
||||
|
||||
var wordA = "fish"
|
||||
var wordB = "hish"
|
||||
var cell : [[Int]] = Array(repeating: Array(repeating: 0, count: wordA.characters.count), count: wordB.characters.count)
|
||||
let wordAArray = wordA.characters.map { String($0) }
|
||||
let wordBArray = wordB.characters.map { String($0) }
|
||||
|
||||
for i in 0...wordA.characters.count-1 {
|
||||
for j in 0...wordB.characters.count-1 {
|
||||
// The letters match
|
||||
if wordAArray[i] == wordBArray[j] {
|
||||
if i > 0 && j > 0 {
|
||||
cell[i][j] = cell[i-1][j-1] + 1
|
||||
} else {
|
||||
cell[i][j] = 1
|
||||
}
|
||||
} else {
|
||||
// The letters don't match.
|
||||
if i > 0 && j > 0 {
|
||||
cell[i][j] = max(cell[i-1][j], cell[i][j-1])
|
||||
} else {
|
||||
cell[i][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
63
11_dynamic_programming/zig/longest_common_subsequence.zig
Normal file
63
11_dynamic_programming/zig/longest_common_subsequence.zig
Normal file
@@ -0,0 +1,63 @@
|
||||
const std = @import("std");
|
||||
const heap = std.heap;
|
||||
const math = std.math;
|
||||
const expect = std.testing.expect;
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = heap.GeneralPurposeAllocator(.{}){};
|
||||
var arena = heap.ArenaAllocator.init(gpa.allocator());
|
||||
defer arena.deinit();
|
||||
|
||||
var n = try subsequence(arena.allocator(), "fish", "fosh");
|
||||
std.debug.print("{d}\n", .{n});
|
||||
}
|
||||
|
||||
fn subsequence(allocator: std.mem.Allocator, a: []const u8, b: []const u8) !u32 {
|
||||
var grid = try allocator.alloc([]u32, a.len + 1);
|
||||
|
||||
for (grid) |*row| {
|
||||
row.* = try allocator.alloc(u32, b.len + 1);
|
||||
for (row.*) |*cell| {
|
||||
cell.* = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var i: usize = 1;
|
||||
while (i <= a.len) : (i += 1) {
|
||||
var j: usize = 1;
|
||||
while (j <= b.len) : (j += 1) {
|
||||
if (a[i - 1] == b[j - 1]) {
|
||||
grid[i][j] = grid[i - 1][j - 1] + 1;
|
||||
} else {
|
||||
grid[i][j] = math.max(grid[i][j - 1], grid[i - 1][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return grid[a.len][b.len];
|
||||
}
|
||||
|
||||
test "subsequence" {
|
||||
var tests = [_]struct {
|
||||
a: []const u8,
|
||||
b: []const u8,
|
||||
exp: u32,
|
||||
}{
|
||||
.{ .a = "abc", .b = "abcd", .exp = 3 },
|
||||
.{ .a = "pera", .b = "mela", .exp = 2 },
|
||||
.{ .a = "banana", .b = "kiwi", .exp = 0 },
|
||||
};
|
||||
|
||||
for (tests) |t| {
|
||||
var gpa = heap.GeneralPurposeAllocator(.{}){};
|
||||
var arena = heap.ArenaAllocator.init(gpa.allocator());
|
||||
defer {
|
||||
arena.deinit();
|
||||
const leaked = gpa.deinit();
|
||||
if (leaked) std.testing.expect(false) catch @panic("TEST FAIL"); //fail test; can't try in defer as defer is executed after we return
|
||||
}
|
||||
|
||||
var n = try subsequence(arena.allocator(), t.a, t.b);
|
||||
try expect(n == t.exp);
|
||||
}
|
||||
}
|
||||
43
11_dynamic_programming/с++/01_longest_common_subsequence.cpp
Normal file
43
11_dynamic_programming/с++/01_longest_common_subsequence.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
int main() {
|
||||
std::string wordA = "Fish", wordB = "Fosh";
|
||||
const size_t& aSize = wordA.size(), &bSize = wordB.size();
|
||||
|
||||
size_t** table = new size_t* [aSize];
|
||||
for (size_t l = 0; l < aSize; ++l)
|
||||
table[l] = new size_t[bSize]{}; // all values in table will be initialized as zero
|
||||
|
||||
for (size_t i = 0; i < aSize; ++i)
|
||||
for (size_t j = 0; j < bSize; ++j)
|
||||
if (wordA[i] == wordB[j])
|
||||
if (i > 0 && j > 0)
|
||||
table[i][j] = table[i - 1][j - 1] + 1;
|
||||
else
|
||||
table[i][j] = 1;
|
||||
else
|
||||
if (i > 0 && j > 0)
|
||||
table[i][j] = std::max(table[i - 1][j], table[i][j - 1]);
|
||||
else if (i == 0 && j > 0)
|
||||
table[i][j] = table[i][j - 1];
|
||||
else if (i > 0 && j == 0)
|
||||
table[i][j] = table[i - 1][j];
|
||||
else
|
||||
table[i][j] = 0;
|
||||
|
||||
for (size_t i = 0; i < aSize; ++i) {
|
||||
std::cout << "[ ";
|
||||
for (size_t j = 0; j < bSize; ++j)
|
||||
std::cout << table[i][j] << ' ';
|
||||
std::cout << ']' << std::endl;
|
||||
}
|
||||
|
||||
// [1 1 1 1]
|
||||
// [1 1 1 1]
|
||||
// [1 1 2 2]
|
||||
// [1 1 2 3]
|
||||
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user