我在最近又試著使用 html tidy 的時候發現這個命令列工具在最近幾年改寫以後,其實只是 libtidy 的包裝。所以也許可以透過 Tcl 呼叫 libtidy 來做到相同的事(而不是 exec tidy tool),所以嘗試寫了一個 Tcl extension,看起來基本的功能和選項設定沒問題,所以我把 code 放一份到 github 了。
2021/01/01 更新
能夠設 encoding 似乎會造成問題,目前先移掉,預設編碼使用 utf8,版本升為 v0.2。
我在最近又試著使用 html tidy 的時候發現這個命令列工具在最近幾年改寫以後,其實只是 libtidy 的包裝。所以也許可以透過 Tcl 呼叫 libtidy 來做到相同的事(而不是 exec tidy tool),所以嘗試寫了一個 Tcl extension,看起來基本的功能和選項設定沒問題,所以我把 code 放一份到 github 了。
2021/01/01 更新
能夠設 encoding 似乎會造成問題,目前先移掉,預設編碼使用 utf8,版本升為 v0.2。
Write a script to replace the character ‘e’ with ‘E’ in the string ‘Weekly Challenge’. Also print the number of times the character ‘e’ is found in the string.
#!/usr/bin/env tclsh
set times [regsub -all "e" "Weekly Challenge" "E" result]
puts "Find e $times times"
puts "Output: $result"
使用 Regular Expressions 來做替代字串的任務。
也可以使用 string map 來替代字串,下面是 Replace e with E 的其它寫法:
#!/usr/bin/env tclsh
set str "Weekly Challenge"
set count 0
foreach x [split $str {}] {
if {$x == "e"} {
incr count
}
}
puts "Find e $count times"
set result [string map {e E} $str]
puts "Output: $result"
也可以在計算 e 數目的時候就同時建構字串:
#!/usr/bin/env tclsh
set str "Weekly Challenge"
set count 0
set result {}
foreach x [split $str {}] {
if {$x == "e"} {
incr count
append result "E"
} else {
append result $x
}
}
puts "Find e $count times"
puts "Output: $result"
下面是 Isomorphic Strings 使用 string first 解的結果:
#!/usr/bin/env tclsh
#
# You are given two strings $A and $B.
# Write a script to check if the given strings are Isomorphic.
# Print 1 if they are otherwise 0.
#
proc isIsomorphic {str1 str2} {
set len [string length $str1]
if {$len != [string length $str2]} {
return 0
}
for {set i 0} {$i < $len} {incr i} {
set floc1 [string first [string index $str1 $i] $str1]
set floc2 [string first [string index $str2 $i] $str2]
if {$floc1 != $floc2} {
return 0
}
}
return 1
}
if {$argc == 2} {
set string1 [lindex $argv 0]
set string2 [lindex $argv 1]
} else {
exit
}
puts [isIsomorphic $string1 $string2]
下面是使用 Tcl 試著解 Count Number 的答案:
#!/usr/bin/tclsh
#
# You are given a positive number $N.
# Write a script to count number and display as you read it.
#
# For example,
# Input: $N = 1122234
# Output: 21321314
# as we read "two 1 three 2 one 3 one 4"
#
puts -nonewline "Please input a number: "
flush stdout
gets stdin number
if {$number <= 0} {
puts "Number requires > 0."
exit
}
array set mapping [list 1 one 2 two 3 three 4 four 5 five 6 six 7 seven 8 eight 9 nine]
set last [string index $number 0]
set index 0
set results [list]
lset results $index [list 1 $last]
for {set i 1} {$i < [string length $number]} {incr i} {
set current [string index $number $i]
if {$current == $last} {
set indexlist [lindex $results $index]
set curval [lindex $indexlist 0]
incr curval
set indexlist [list $curval $current]
} else {
incr index
set indexlist [list 1 $current]
}
lset results $index $indexlist
set last $current
}
set answer {}
foreach r $results {
append answer [join $r ""]
}
puts "\nOutput: $answer"
puts -nonewline "as we read \""
set nresults [list]
for {set index 0} {$index < [llength $results]} {incr index} {
set r [lindex $results $index]
set key [lindex $r 0]
set value [lindex $r 1]
lappend nresults "$mapping($key) $value"
}
puts -nonewline [join $nresults " "]
puts "\""
下面是試著使用 Tcl 解 DNA Sequence 問題的解法:
#!/usr/bin/env tclsh
#
# DNA is a long, chainlike molecule which has two strands twisted
# into a double helix. The two strands are made up of simpler molecules
# called nucleotides. Each nucleotide is composed of one of the
# four nitrogen-containing nucleobases cytosine (C), guanine (G),
# adenine (A) and thymine (T).
# Write a script to print nucleobase count in the given DNA sequence.
# Also print the complementary sequence where Thymine (T) on one strand
# is always facing an adenine (A) and vice versa; guanine (G) is always
# facing a cytosine (C) and vice versa.
#
set dna "GTAAACCCCTTTTCATTTAGACAGATCGACTCCTTATCCATTCTCAGAGATGTGTTGCTGGTCGCCG"
set ccount [llength [regexp -all -inline "C" $dna]]
set gcount [llength [regexp -all -inline "G" $dna]]
set acount [llength [regexp -all -inline "A" $dna]]
set tcount [llength [regexp -all -inline "T" $dna]]
puts "C: $ccount"
puts "G: $gcount"
puts "A: $acount"
puts "T: $tcount"
set complement ""
set length [string length $dna]
for {set i 0} {$i < $length} {incr i} {
set substring [string index $dna $i]
if {[string compare $substring "C"]==0} {
append complement "G"
} elseif {[string compare $substring "G"]==0} {
append complement "C"
} elseif {[string compare $substring "A"]==0} {
append complement "T"
} elseif {[string compare $substring "T"]==0} {
append complement "A"
}
}
puts ""
puts "Complement:"
puts $complement
也可以這樣寫:
#!/usr/bin/env tclsh
#
# DNA is a long, chainlike molecule which has two strands twisted
# into a double helix. The two strands are made up of simpler molecules
# called nucleotides. Each nucleotide is composed of one of the
# four nitrogen-containing nucleobases cytosine (C), guanine (G),
# adenine (A) and thymine (T).
# Write a script to print nucleobase count in the given DNA sequence.
# Also print the complementary sequence where Thymine (T) on one strand
# is always facing an adenine (A) and vice versa; guanine (G) is always
# facing a cytosine (C) and vice versa.
#
set dna "GTAAACCCCTTTTCATTTAGACAGATCGACTCCTTATCCATTCTCAGAGATGTGTTGCTGGTCGCCG"
set ccount 0
set gcount 0
set acount 0
set tcount 0
set complement ""
set length [string length $dna]
for {set i 0} {$i < $length} {incr i} {
set substring [string index $dna $i]
if {[string compare $substring "C"]==0} {
incr ccount
append complement "G"
} elseif {[string compare $substring "G"]==0} {
incr gcount
append complement "C"
} elseif {[string compare $substring "A"]==0} {
incr acount
append complement "T"
} elseif {[string compare $substring "T"]==0} {
incr tcount
append complement "A"
}
}
puts "C: $ccount"
puts "G: $gcount"
puts "A: $acount"
puts "T: $tcount"
puts ""
puts "Complement:"
puts $complement
如果使用 array 實作,就會是下面的樣子:
#!/usr/bin/env tclsh
#
# DNA is a long, chainlike molecule which has two strands twisted
# into a double helix. The two strands are made up of simpler molecules
# called nucleotides. Each nucleotide is composed of one of the
# four nitrogen-containing nucleobases cytosine (C), guanine (G),
# adenine (A) and thymine (T).
# Write a script to print nucleobase count in the given DNA sequence.
# Also print the complementary sequence where Thymine (T) on one strand
# is always facing an adenine (A) and vice versa; guanine (G) is always
# facing a cytosine (C) and vice versa.
#
set dna "GTAAACCCCTTTTCATTTAGACAGATCGACTCCTTATCCATTCTCAGAGATGTGTTGCTGGTCGCCG"
set complement ""
array set count {}
set length [string length $dna]
for {set i 0} {$i < $length} {incr i} {
set substring [string index $dna $i]
incr count($substring)
switch $substring {
"C" {
append complement "G"
}
"G" {
append complement "C"
}
"A" {
append complement "T"
}
"T" {
append complement "A"
}
}
}
foreach {key value} [array get count] {
puts "$key: $value"
}
puts ""
puts "Complement:"
puts $complement