consolidated go and scala repos into this repo as well

This commit is contained in:
Fizzizist
2025-01-04 16:03:27 -05:00
parent af2ce045ec
commit 8d4cc2b83c
20 changed files with 535 additions and 0 deletions

5
go/README.md Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,2 @@
GATATATGCATATACTT
ATAT