consolidated go and scala repos into this repo as well
This commit is contained in:
5
go/README.md
Normal file
5
go/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# go-rosalind
|
||||
|
||||
go-rosalind is a command-line utility for running solutions to [Rosalind.info](rosalind.info) problems that were written in go.
|
||||
|
||||
This is mostly just used by me to consolidate some repeated code and practice writing stuff in Go.
|
||||
19
go/cmd/cons.go
Normal file
19
go/cmd/cons.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"gitlab.com/fizzizist/go-rosalind/pkg/solutions"
|
||||
)
|
||||
|
||||
var consCmd = &cobra.Command{
|
||||
Use: "cons",
|
||||
Short: "Finds a Motif in input DNA",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
solutions.Cons(args[0])
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(consCmd)
|
||||
}
|
||||
12
go/cmd/root.go
Normal file
12
go/cmd/root.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "go-rosalind",
|
||||
Short: "An app for running Rosalind solutions",
|
||||
}
|
||||
|
||||
func Execute() error {
|
||||
return rootCmd.Execute()
|
||||
}
|
||||
19
go/cmd/subs.go
Normal file
19
go/cmd/subs.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"gitlab.com/fizzizist/go-rosalind/pkg/solutions"
|
||||
)
|
||||
|
||||
var dnaMotifsCmd = &cobra.Command{
|
||||
Use: "subs",
|
||||
Short: "Finds a Motif in input DNA",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
solutions.FindMotifs(args[0])
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(dnaMotifsCmd)
|
||||
}
|
||||
15
go/main.go
Normal file
15
go/main.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"gitlab.com/fizzizist/go-rosalind/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
86
go/pkg/io/file_tools.go
Normal file
86
go/pkg/io/file_tools.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func FileToStringArray(filename string) ([]string, error) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
var fileLines []string
|
||||
|
||||
for scanner.Scan() {
|
||||
fileLines = append(fileLines, scanner.Text())
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file.Close()
|
||||
|
||||
return fileLines, nil
|
||||
}
|
||||
|
||||
func WriteStringsToFile(content []string, filepath string) error {
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w := bufio.NewWriter(file)
|
||||
|
||||
for _, line := range content {
|
||||
_, err = fmt.Fprintln(w, line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = w.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = file.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseFasta parses a .fasta formatted file returning a list of labels and a list of
|
||||
// content in separate string arrays.
|
||||
func ParseFasta(filename string) ([]string, []string, error) {
|
||||
lines, err := FileToStringArray(filename)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var labels []string
|
||||
var content []string
|
||||
var currString []string
|
||||
for _, line := range lines {
|
||||
if line[0] == '>' {
|
||||
labels = append(labels, line)
|
||||
if len(currString) > 0 {
|
||||
content = append(content, strings.Join(currString, ""))
|
||||
currString = []string{}
|
||||
}
|
||||
continue
|
||||
}
|
||||
currString = append(currString, line)
|
||||
}
|
||||
if len(currString) > 0 {
|
||||
content = append(content, strings.Join(currString, ""))
|
||||
}
|
||||
|
||||
return labels, content, nil
|
||||
}
|
||||
76
go/pkg/solutions/cons.go
Normal file
76
go/pkg/solutions/cons.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package solutions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitlab.com/fizzizist/go-rosalind/pkg/io"
|
||||
)
|
||||
|
||||
func CompileOutput(consensus string, profile [][]int) []string {
|
||||
output := []string{consensus}
|
||||
idxMap := []string{"A", "C", "G", "T"}
|
||||
|
||||
for i, val := range profile {
|
||||
var strProf []string
|
||||
for _, inVal := range val {
|
||||
strProf = append(strProf, strconv.Itoa(inVal))
|
||||
}
|
||||
output = append(output, fmt.Sprintf("%s: %s", idxMap[i], strings.Join(strProf, " ")))
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
func Cons(filename string) {
|
||||
_, lines, err := io.ParseFasta(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read file: %s", err)
|
||||
}
|
||||
|
||||
profile := make([][]int, 4) // 1 for each codon
|
||||
for i := range profile {
|
||||
profile[i] = make([]int, len(lines[1]))
|
||||
}
|
||||
|
||||
for _, value := range lines {
|
||||
for j, s := range value {
|
||||
switch {
|
||||
case s == 'A':
|
||||
profile[0][j]++
|
||||
case s == 'C':
|
||||
profile[1][j]++
|
||||
case s == 'G':
|
||||
profile[2][j]++
|
||||
case s == 'T':
|
||||
profile[3][j]++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var consensus []string
|
||||
idxMap := []string{"A", "C", "G", "T"}
|
||||
for i := range profile[0] {
|
||||
maxCons := "A"
|
||||
maxVal := 0
|
||||
for j, s := range idxMap {
|
||||
if profile[j][i] > maxVal {
|
||||
maxCons = s
|
||||
maxVal = profile[j][i]
|
||||
}
|
||||
}
|
||||
consensus = append(consensus, maxCons)
|
||||
}
|
||||
|
||||
fmt.Println("Writing output file...")
|
||||
err = io.WriteStringsToFile(
|
||||
CompileOutput(strings.Join(consensus, ""), profile),
|
||||
"results/cons.txt",
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed writing output file: %s", err)
|
||||
}
|
||||
fmt.Println("Done.")
|
||||
}
|
||||
33
go/pkg/solutions/subs.go
Normal file
33
go/pkg/solutions/subs.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package solutions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitlab.com/fizzizist/go-rosalind/pkg/io"
|
||||
)
|
||||
|
||||
func FindMotifs(filename string) {
|
||||
lines, err := io.FileToStringArray(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read file: %s", err)
|
||||
}
|
||||
if len(lines) != 2 {
|
||||
log.Fatalf("Input file should have exactly 2 lines, a DNA string and a motif")
|
||||
}
|
||||
|
||||
dna := lines[0]
|
||||
motif := lines[1]
|
||||
motLen := len(motif)
|
||||
var positions []string
|
||||
|
||||
for i := 0; i <= len(dna)-motLen; i++ {
|
||||
if motif == dna[i:i+motLen] {
|
||||
positions = append(positions, strconv.Itoa(i+1))
|
||||
}
|
||||
}
|
||||
fmt.Println(strings.Join(positions, " "))
|
||||
|
||||
}
|
||||
14
go/testing/cons.fasta
Normal file
14
go/testing/cons.fasta
Normal file
@@ -0,0 +1,14 @@
|
||||
>Rosalind_1
|
||||
ATCCAGCT
|
||||
>Rosalind_2
|
||||
GGGCAACT
|
||||
>Rosalind_3
|
||||
ATGGATCT
|
||||
>Rosalind_4
|
||||
AAGCAACC
|
||||
>Rosalind_5
|
||||
TTGGAACT
|
||||
>Rosalind_6
|
||||
ATGCCATT
|
||||
>Rosalind_7
|
||||
ATGGCACT
|
||||
2
go/testing/subs.txt
Normal file
2
go/testing/subs.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
GATATATGCATATACTT
|
||||
ATAT
|
||||
Reference in New Issue
Block a user