Skip to content

Commit 78ed2ef

Browse files
authored
Add Longest Common Subsequence in Tcl (#5065)
1 parent a1b9c71 commit 78ed2ef

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package require Tcl 8.6
2+
package require struct::matrix
3+
4+
proc usage {} {
5+
puts stderr {Usage: please provide two lists in the format "1, 2, 3, 4, 5"}
6+
exit 1
7+
}
8+
9+
proc parseList {s} {
10+
set result {}
11+
foreach t [split $s ","] {
12+
set t [string trim $t]
13+
if {$t eq "" || [catch {expr {int($t)}} val]} { usage }
14+
lappend result $val
15+
}
16+
return $result
17+
}
18+
19+
proc formatList {lst} {
20+
return [join $lst ", "]
21+
}
22+
23+
proc decr {varName {by 1}} {
24+
upvar 1 $varName v
25+
set v [expr {$v - $by}]
26+
return $v
27+
}
28+
29+
proc getCell {matrix i j} {
30+
set v [eval $matrix get cell $j $i]
31+
return [expr {($v eq "") ? 0 : $v}]
32+
}
33+
34+
proc longestCommonSubsequence {a b} {
35+
set n [llength $a]
36+
set m [llength $b]
37+
38+
::struct::matrix dp
39+
dp add rows [expr {$n + 1}]
40+
dp add columns [expr {$m + 1}]
41+
42+
for {set row 1} {$row <= $n} {incr row} {
43+
set valA [lindex $a [expr {$row - 1}]]
44+
for {set col 1} {$col <= $m} {incr col} {
45+
set valB [lindex $b [expr {$col - 1}]]
46+
if {$valA eq $valB} {
47+
set diag [getCell dp [expr {$row-1}] [expr {$col-1}]]
48+
dp set cell $col $row [expr {$diag + 1}]
49+
} else {
50+
set top [getCell dp [expr {$row-1}] $col]
51+
set left [getCell dp $row [expr {$col-1}]]
52+
dp set cell $col $row [expr {max($top, $left)}]
53+
}
54+
}
55+
}
56+
57+
set lcs {}
58+
set row $n
59+
set col $m
60+
while {$row > 0 && $col > 0} {
61+
set valA [lindex $a [expr {$row - 1}]]
62+
set valB [lindex $b [expr {$col - 1}]]
63+
set top [getCell dp [expr {$row-1}] $col]
64+
set left [getCell dp $row [expr {$col-1}]]
65+
66+
if {$valA eq $valB} {
67+
lappend lcs $valA
68+
decr row; decr col
69+
} elseif {$top >= $left} {
70+
decr row
71+
} else {
72+
decr col
73+
}
74+
}
75+
76+
return [lreverse $lcs]
77+
}
78+
79+
if {$argc != 2} { usage }
80+
81+
set a [parseList [lindex $argv 0]]
82+
set b [parseList [lindex $argv 1]]
83+
84+
set lcs [longestCommonSubsequence $a $b]
85+
86+
if {[llength $lcs] == 0} {
87+
puts "No common subsequence."
88+
} else {
89+
puts [formatList $lcs]
90+
}
91+

0 commit comments

Comments
 (0)