Skip to content

Commit 325023c

Browse files
committed
Fix algorithm
1 parent c835b74 commit 325023c

File tree

1 file changed

+56
-71
lines changed

1 file changed

+56
-71
lines changed

Algorithms/Strings/MinCostStringConversion.fs

Lines changed: 56 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -9,90 +9,75 @@
99
namespace Algorithms.Strings
1010

1111
module MinCostStringConversion =
12+
13+
[<RequireQualifiedAccess>]
14+
type Operation =
15+
| Copy of char
16+
| Replace of Source: char * Target: char
17+
| Delete of char
18+
| Insert of char
19+
1220
let computeTransformTables
1321
(
14-
sourceString: string,
15-
destinationString: string,
22+
source: string,
23+
destination: string,
1624
copyCost: int,
1725
replaceCost: int,
1826
deleteCost: int,
1927
insertCost: int
20-
): list<int> * list<string> =
21-
let sourceSeq = [ sourceString ]
22-
let destinationSeq = [ destinationString ]
23-
let lenSourceSeq = sourceSeq.Length
24-
let lenDestinationSeq = destinationSeq.Length
25-
28+
): array<array<int>> * array<array<Operation>> =
29+
2630
let costs =
27-
[| for i in 0 .. (lenSourceSeq + 1) -> [| for i in 0 .. lenDestinationSeq + 1 -> 0 |] |]
28-
31+
Array.init (source.Length + 1) (fun _ -> Array.init (destination.Length + 1) (fun _ -> None))
32+
2933
let ops =
30-
[| for i in 0 .. lenSourceSeq + 1 -> [| for i in 0 .. lenDestinationSeq + 1 -> "" |] |]
31-
32-
for i = 1 to lenSourceSeq + 1 do
33-
costs.[i].[0] <- i * deleteCost
34-
ops.[i].[0] <- sprintf "D%s" (sourceSeq.[i - 1])
35-
36-
for i = 1 to lenDestinationSeq + 1 do
37-
costs.[0].[i] <- i * insertCost
38-
ops.[0].[i] <- sprintf "I%s" (destinationSeq.[i - 1])
39-
40-
for i in 1 .. lenSourceSeq + 1 do
41-
for j in 1 .. lenDestinationSeq + 1 do
42-
if sourceSeq.[i - 1] = destinationSeq.[j - 1] then
43-
costs.[i].[j] <- costs.[i - 1].[j - 1] + copyCost
44-
ops.[i].[j] <- sprintf "C%s" (sourceSeq.[i - 1])
34+
Array.init (source.Length + 1) (fun _ -> Array.init (destination.Length + 1) (fun _ -> None))
35+
36+
costs.[0].[0] <- Some 0
37+
ops.[0].[0] <- Some (Operation.Copy 'a') // There is no operation to perform, assigning dummy operation to satisfy compiler
38+
39+
40+
for i = 1 to source.Length do
41+
costs.[i].[0] <- Some (i * deleteCost)
42+
ops.[i].[0] <- Some (Operation.Delete source.[i - 1])
43+
44+
for i = 1 to destination.Length do
45+
costs.[0].[i] <- Some (i * insertCost)
46+
ops.[0].[i] <- Some (Operation.Insert destination.[i - 1])
47+
48+
for i in 1 .. source.Length do
49+
for j in 1 .. destination.Length do
50+
if source.[i - 1] = destination.[j - 1] then
51+
costs.[i].[j] <- Some (costs.[i - 1].[j - 1].Value + copyCost)
52+
ops.[i].[j] <- Some (Operation.Copy (source.[i - 1]))
4553
else
46-
costs.[i].[j] <- costs.[i - 1].[j - 1] + replaceCost
47-
48-
ops.[i].[j] <-
49-
sprintf
50-
"R%s"
51-
(sourceSeq.[i - 1]
52-
+ (string) (destinationSeq.[j - 1]))
54+
costs.[i].[j] <- Some (costs.[i - 1].[j - 1].Value + replaceCost)
55+
ops.[i].[j] <- Some (Operation.Replace (source.[i - 1], destination.[j - 1]))
5356

54-
if costs.[i - 1].[j] + deleteCost < costs.[i].[j] then
55-
costs.[i].[j] <- costs.[i - 1].[j] + deleteCost
56-
ops.[i].[j] <- sprintf "D%s" (sourceSeq.[i - 1])
57+
if costs.[i - 1].[j].Value + deleteCost < costs.[i].[j].Value then
58+
costs.[i].[j] <- Some (costs.[i - 1].[j].Value + deleteCost)
59+
ops.[i].[j] <- Some (Operation.Delete (source.[i - 1]))
5760

58-
if costs.[i].[j - 1] + insertCost < costs.[i].[j] then
59-
costs.[i].[j] <- costs.[i].[j - 1] + insertCost
60-
ops.[i].[j] <- sprintf "I%s" (destinationSeq.[j - 1])
61+
if costs.[i].[j - 1].Value + insertCost < costs.[i].[j].Value then
62+
costs.[i].[j] <- Some (costs.[i].[j - 1].Value + insertCost)
63+
ops.[i].[j] <- Some (Operation.Insert destination.[j - 1])
6164

62-
costs |> Seq.cast<int> |> Seq.toList, ops |> Seq.cast<string> |> Seq.toList
65+
costs |> Array.map (Array.map Option.get), ops |> Array.map (Array.map Option.get)
6366

64-
let rec assembleTransformation (ops: list<string>, i: int, j: int): list<string> =
67+
let rec assembleTransformation (ops: array<array<Operation>>, i: int, j: int): array<Operation> =
68+
printfn $"i={i},j={j},%A{ops}"
6569
if i = 0 && j = 0 then
66-
List.empty
70+
Array.empty
6771
else
6872
match ops.[i].[j] with
69-
| o when o = 'C' || o = 'R' ->
70-
let mutable seq =
71-
assembleTransformation (ops, i - 1, j - 1)
72-
|> List.toArray
73-
74-
let ch =
75-
[ ((string) ops.[i].[j]) ] |> List.toArray
76-
77-
seq <- seq |> Array.append ch
78-
seq |> List.ofArray
79-
| 'D' ->
80-
let mutable seq =
81-
assembleTransformation (ops, i - 1, j)
82-
|> List.toArray
83-
84-
let ch =
85-
[ ((string) ops.[i].[j]) ] |> List.toArray
86-
87-
seq <- seq |> Array.append ch
88-
seq |> List.ofArray
89-
| _ ->
90-
let mutable seq =
91-
assembleTransformation (ops, i, j - 1)
92-
|> List.toArray
93-
94-
let ch =
95-
[ ((string) ops.[i].[j]) ] |> List.toArray
96-
97-
seq <- seq |> Array.append ch
98-
seq |> List.ofArray
73+
| Operation.Replace _
74+
| Operation.Copy _ ->
75+
let seq = assembleTransformation (ops, i - 1, j - 1)
76+
Array.append seq [| ops[i][j] |]
77+
| Operation.Delete _ ->
78+
let seq = assembleTransformation (ops, i - 1, j)
79+
Array.append seq [| ops[i][j] |]
80+
| Operation.Insert _ ->
81+
let seq = assembleTransformation (ops, i , j - 1)
82+
Array.append seq [| ops[i][j] |]
83+

0 commit comments

Comments
 (0)