From f75636a7697bf13606a538c0773e30fa24caa746 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Thu, 31 Dec 2020 20:26:08 +0100 Subject: [PATCH 1/4] For each codon, find synonym with most C & G --- best-codon.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 best-codon.go diff --git a/best-codon.go b/best-codon.go new file mode 100644 index 0000000..4e30e53 --- /dev/null +++ b/best-codon.go @@ -0,0 +1,96 @@ +package main + +import ( + "encoding/csv" + "fmt" + "log" + "os" + "sort" + "strings" +) + +// modified from https://stackoverflow.com/questions/37562873/most-idiomatic-way-to-select-elements-from-an-array-in-golang +func filter(ss [][]string, test func([]string) bool) (ret [][]string) { + for _, s := range ss { + if test(s) { + ret = append(ret, s) + } + } + return +} + +// from https://stackoverflow.com/questions/24999079/reading-csv-file-in-go +func readCsvFile(filePath string) [][]string { + f, err := os.Open(filePath) + if err != nil { + log.Fatal("Unable to read input file " + filePath, err) + } + defer f.Close() + + csvReader := csv.NewReader(f) + records, err := csvReader.ReadAll() + if err != nil { + log.Fatal("Unable to parse file as CSV for " + filePath, err) + } + + return records +} + +// from https://gobyexample.com/sorting-by-functions +type byBestSynonym [][]string + +func (s byBestSynonym) Len() int { + return len(s) +} + +func (s byBestSynonym) Swap(i, j int) { + s[i][1], s[j][1] = s[j][1], s[i][1] +} + +// sort by highest occurance of C and G +func (s byBestSynonym) Less(i, j int) bool { + return strings.Count(s[i][1], "C") + strings.Count(s[i][1], "G") > strings.Count(s[j][1], "C") + strings.Count(s[j][1], "G") +} + +func bestCodon(amino string, codons [][]string) string { + synonym := func(s []string) bool { return s[0] == amino } + synonyms := filter(codons, synonym) + sort.Sort(byBestSynonym(synonyms)) + return synonyms[0][1] +} + + +func main() { + // Read the codon/amino acid table + codons := readCsvFile("codon-table-grouped.csv")[1:] + + c2s:= make(map[string]string) + for _, element := range codons { + c2s[element[1]]=element[0] + } + + // read the codons + virvac := readCsvFile("side-by-side.csv")[1:] + + matches := 0.0 + for _, element := range virvac { + vir:=element[1] + vac:=element[2] + var our string + fmt.Printf("%s v %s, amino: %s == %s. ", + vir, vac, + c2s[vir], c2s[vac]) + + our = bestCodon(c2s[vir], codons) + + fmt.Printf(" ") + if(vac == our) { + fmt.Printf("Matched the vaccine!\n") + matches++ + } else { + fmt.Printf("No match.\n") + } + } + fmt.Printf("%.1f%%\n", 100.0*matches/float64(len(virvac))) + +} From 7db9597993713cef4d82a98c00ea69d90d2f66c9 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Thu, 31 Dec 2020 20:32:31 +0100 Subject: [PATCH 2/4] Show our attempt if it doesn't match --- best-codon.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/best-codon.go b/best-codon.go index 4e30e53..1ef0c66 100644 --- a/best-codon.go +++ b/best-codon.go @@ -88,7 +88,7 @@ func main() { fmt.Printf("Matched the vaccine!\n") matches++ } else { - fmt.Printf("No match.\n") + fmt.Printf("No match (%s)\n", our) } } fmt.Printf("%.1f%%\n", 100.0*matches/float64(len(virvac))) From b903bea2937a90b7b5d714c5a27227334ca060a1 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Thu, 31 Dec 2020 20:46:36 +0100 Subject: [PATCH 3/4] Extract score() function --- best-codon.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/best-codon.go b/best-codon.go index 1ef0c66..cb4c4de 100644 --- a/best-codon.go +++ b/best-codon.go @@ -47,9 +47,13 @@ func (s byBestSynonym) Swap(i, j int) { s[i][1], s[j][1] = s[j][1], s[i][1] } +func score(codon string) int { + return strings.Count(codon, "C") + strings.Count(codon, "G") +} + // sort by highest occurance of C and G func (s byBestSynonym) Less(i, j int) bool { - return strings.Count(s[i][1], "C") + strings.Count(s[i][1], "G") > strings.Count(s[j][1], "C") + strings.Count(s[j][1], "G") + return score(s[i][1]) > score(s[j][1]) } func bestCodon(amino string, codons [][]string) string { From 266fb1ec39df771882abb93bb97784b1ee084515 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Thu, 31 Dec 2020 20:49:12 +0100 Subject: [PATCH 4/4] Never change a winning team Increases matches from 62.4% to 62.7% --- best-codon.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/best-codon.go b/best-codon.go index cb4c4de..606318e 100644 --- a/best-codon.go +++ b/best-codon.go @@ -56,11 +56,16 @@ func (s byBestSynonym) Less(i, j int) bool { return score(s[i][1]) > score(s[j][1]) } -func bestCodon(amino string, codons [][]string) string { +func bestCodon(amino string, virus_codon string, codons [][]string) string { synonym := func(s []string) bool { return s[0] == amino } synonyms := filter(codons, synonym) sort.Sort(byBestSynonym(synonyms)) - return synonyms[0][1] + winner := synonyms[0][1] + // Never change a winning team: + if score(winner) == score(virus_codon) { + return virus_codon + } + return winner } @@ -85,7 +90,7 @@ func main() { vir, vac, c2s[vir], c2s[vac]) - our = bestCodon(c2s[vir], codons) + our = bestCodon(c2s[vir], vir, codons) fmt.Printf(" ") if(vac == our) {