171 lines
4.9 KiB
Go
171 lines
4.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
/* Gets n! for small n. */
|
|
func factorial(n int) int {
|
|
fact := 1
|
|
for i := 2; i <= n; i++ {
|
|
fact *= i
|
|
}
|
|
return fact
|
|
}
|
|
|
|
/* Gets all permutations of a list of strings. */
|
|
func getPerms(input []string) [][]string {
|
|
perms := [][]string{input}
|
|
le := len(input)
|
|
a := make([]string, le)
|
|
copy(a, input)
|
|
n := le - 1
|
|
fact := factorial(n + 1)
|
|
|
|
for c := 1; c < fact; c++ {
|
|
i := n - 1
|
|
j := n
|
|
for i >= 0 && a[i] > a[i+1] {
|
|
i--
|
|
}
|
|
if i == -1 {
|
|
i = n
|
|
}
|
|
for a[j] < a[i] {
|
|
j--
|
|
}
|
|
a[i], a[j] = a[j], a[i]
|
|
j = n
|
|
i++
|
|
if i == n+1 {
|
|
i = 0
|
|
}
|
|
for i < j {
|
|
a[i], a[j] = a[j], a[i]
|
|
i++
|
|
j--
|
|
}
|
|
b := make([]string, le)
|
|
copy(b, a)
|
|
perms = append(perms, b)
|
|
}
|
|
return perms
|
|
}
|
|
|
|
/* Returns all distinct elements from a list of strings. */
|
|
func distinct(slist []string) []string {
|
|
distinctSet := make(map[string]int, len(slist))
|
|
i := 0
|
|
for _, s := range slist {
|
|
if _, ok := distinctSet[s]; !ok {
|
|
distinctSet[s] = i
|
|
i++
|
|
}
|
|
}
|
|
result := make([]string, len(distinctSet))
|
|
for s, i := range distinctSet {
|
|
result[i] = s
|
|
}
|
|
return result
|
|
}
|
|
|
|
/* Given a DNA sequence, report the sequence, length and base counts. */
|
|
func printCounts(seq string) {
|
|
bases := [][]rune{{'A', 0}, {'C', 0}, {'G', 0}, {'T', 0}}
|
|
for _, c := range seq {
|
|
for _, base := range bases {
|
|
if c == base[0] {
|
|
base[1]++
|
|
}
|
|
}
|
|
}
|
|
sum := 0
|
|
fmt.Println("\nNucleotide counts for", seq, "\b:\n")
|
|
for _, base := range bases {
|
|
fmt.Printf("%10c%12d\n", base[0], base[1])
|
|
sum += int(base[1])
|
|
}
|
|
le := len(seq)
|
|
fmt.Printf("%10s%12d\n", "Other", le-sum)
|
|
fmt.Printf(" ____________________\n%14s%8d\n", "Total length", le)
|
|
}
|
|
|
|
/* Return the position in s1 of the start of overlap of tail of string s1 with head of string s2. */
|
|
func headTailOverlap(s1, s2 string) int {
|
|
for start := 0; ; start++ {
|
|
ix := strings.IndexByte(s1[start:], s2[0])
|
|
if ix == -1 {
|
|
return 0
|
|
} else {
|
|
start += ix
|
|
}
|
|
if strings.HasPrefix(s2, s1[start:]) {
|
|
return len(s1) - start
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Remove duplicates and strings contained within a larger string from a list of strings. */
|
|
func deduplicate(slist []string) []string {
|
|
var filtered []string
|
|
arr := distinct(slist)
|
|
for i, s1 := range arr {
|
|
withinLarger := false
|
|
for j, s2 := range arr {
|
|
if j != i && strings.Contains(s2, s1) {
|
|
withinLarger = true
|
|
break
|
|
}
|
|
}
|
|
if !withinLarger {
|
|
filtered = append(filtered, s1)
|
|
}
|
|
}
|
|
return filtered
|
|
}
|
|
|
|
/* Returns shortest common superstring of a list of strings. */
|
|
func shortestCommonSuperstring(slist []string) string {
|
|
ss := deduplicate(slist)
|
|
shortestSuper := strings.Join(ss, "")
|
|
for _, perm := range getPerms(ss) {
|
|
sup := perm[0]
|
|
for i := 0; i < len(ss)-1; i++ {
|
|
overlapPos := headTailOverlap(perm[i], perm[i+1])
|
|
sup += perm[i+1][overlapPos:]
|
|
}
|
|
if len(sup) < len(shortestSuper) {
|
|
shortestSuper = sup
|
|
}
|
|
}
|
|
return shortestSuper
|
|
}
|
|
|
|
func main() {
|
|
testSequences := [][]string{
|
|
{"TA", "AAG", "TA", "GAA", "TA"},
|
|
{"CATTAGGG", "ATTAG", "GGG", "TA"},
|
|
{"AAGAUGGA", "GGAGCGCAUC", "AUCGCAAUAAGGA"},
|
|
{
|
|
"ATGAAATGGATGTTCTGAGTTGGTCAGTCCCAATGTGCGGGGTTTCTTTTAGTACGTCGGGAGTGGTATTAT",
|
|
"GGTCGATTCTGAGGACAAAGGTCAAGATGGAGCGCATCGAACGCAATAAGGATCATTTGATGGGACGTTTCGTCGACAAAGT",
|
|
"CTATGTTCTTATGAAATGGATGTTCTGAGTTGGTCAGTCCCAATGTGCGGGGTTTCTTTTAGTACGTCGGGAGTGGTATTATA",
|
|
"TGCTTTCCAATTATGTAAGCGTTCCGAGACGGGGTGGTCGATTCTGAGGACAAAGGTCAAGATGGAGCGCATC",
|
|
"AACGCAATAAGGATCATTTGATGGGACGTTTCGTCGACAAAGTCTTGTTTCGAGAGTAACGGCTACCGTCTT",
|
|
"GCGCATCGAACGCAATAAGGATCATTTGATGGGACGTTTCGTCGACAAAGTCTTGTTTCGAGAGTAACGGCTACCGTC",
|
|
"CGTTTCGTCGACAAAGTCTTGTTTCGAGAGTAACGGCTACCGTCTTCGATTCTGCTTATAACACTATGTTCT",
|
|
"TGCTTTCCAATTATGTAAGCGTTCCGAGACGGGGTGGTCGATTCTGAGGACAAAGGTCAAGATGGAGCGCATC",
|
|
"CGTAAAAAATTACAACGTCCTTTGGCTATCTCTTAAACTCCTGCTAAATGCTCGTGC",
|
|
"GATGGAGCGCATCGAACGCAATAAGGATCATTTGATGGGACGTTTCGTCGACAAAGTCTTGTTTCGAGAGTAACGGCTACCGTCTTCGATT",
|
|
"TTTCCAATTATGTAAGCGTTCCGAGACGGGGTGGTCGATTCTGAGGACAAAGGTCAAGATGGAGCGCATC",
|
|
"CTATGTTCTTATGAAATGGATGTTCTGAGTTGGTCAGTCCCAATGTGCGGGGTTTCTTTTAGTACGTCGGGAGTGGTATTATA",
|
|
"TCTCTTAAACTCCTGCTAAATGCTCGTGCTTTCCAATTATGTAAGCGTTCCGAGACGGGGTGGTCGATTCTGAGGACAAAGGTCAAGA",
|
|
},
|
|
}
|
|
|
|
for _, test := range testSequences {
|
|
scs := shortestCommonSuperstring(test)
|
|
printCounts(scs)
|
|
}
|
|
}
|