go: lay groundwork for matrix traversal
This commit is contained in:
parent
76421d76a8
commit
1b361e5146
63
main.go
63
main.go
|
@ -3,10 +3,71 @@
|
|||
|
||||
package main
|
||||
|
||||
import "log"
|
||||
import (
|
||||
"encoding/csv"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
mFlagDescr = "path to a CSV file containing matrix values"
|
||||
aFlagDescr = "read matrix from stdin-provided arg"
|
||||
usage = `Usage of diwt:
|
||||
-m, --matrixfile ` + mFlagDescr + `
|
||||
-a, --stdin ` + aFlagDescr + `
|
||||
-h, --help prints help information
|
||||
`
|
||||
)
|
||||
|
||||
var version = "development"
|
||||
|
||||
func main() {
|
||||
log.Println("starting diwt, version", version)
|
||||
|
||||
var f string
|
||||
|
||||
var a string
|
||||
|
||||
flag.StringVar(&f, "matrixfile", "", mFlagDescr)
|
||||
flag.StringVar(&f, "m", "", mFlagDescr)
|
||||
flag.StringVar(&a, "stdin", "", aFlagDescr)
|
||||
flag.StringVar(&a, "a", "", aFlagDescr)
|
||||
|
||||
flag.Usage = func() { fmt.Fprint(os.Stderr, usage) }
|
||||
|
||||
flag.Parse()
|
||||
|
||||
var r csv.Reader
|
||||
|
||||
switch {
|
||||
case f == "" && a == "":
|
||||
log.Println("no file provided, bailing...")
|
||||
os.Exit(3)
|
||||
|
||||
case a != "" && f != "":
|
||||
log.Println(
|
||||
"only provide one of the flags (file or stdin), not both. " +
|
||||
"exiting.",
|
||||
)
|
||||
os.Exit(4)
|
||||
|
||||
case f != "":
|
||||
r = readFile(f)
|
||||
|
||||
case a != "":
|
||||
r = readArg(a)
|
||||
}
|
||||
|
||||
records, err := r.ReadAll()
|
||||
if err != nil {
|
||||
log.Fatalln("error reading records:", err)
|
||||
}
|
||||
|
||||
m := convertMatrix(records)
|
||||
|
||||
traverseMatrixMinSumPath(m)
|
||||
|
||||
log.Println("looks like we're done here.")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2022 wanderer <wanderer at dotya.ml>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type matrix struct {
|
||||
rows [][]int
|
||||
}
|
||||
|
||||
// stoi attempts to convert a supposed int in string form to an actual int,
|
||||
// fails loudly if it doesn't work.
|
||||
func stoi(s string) int {
|
||||
val, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
log.Fatalln("could not convert from string to int:", s, err)
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
// rowtoi converts a row (a []string) to an []int and returns it.
|
||||
func rowtoi(row []string) []int {
|
||||
cols := len(row)
|
||||
|
||||
// prealloc, when the size is known, gosimple is wrong here.
|
||||
intRow := make([]int, cols, cols) //nolint:gosimple
|
||||
|
||||
for i, v := range row {
|
||||
intRow[i] = stoi(v)
|
||||
}
|
||||
|
||||
return intRow
|
||||
}
|
||||
|
||||
// isNonEmptyMatrix checks the [][]string input and determines whether it is a
|
||||
// non-empty matrix, since that is the kind we care about.
|
||||
func isNonEmptyMatrix(strmatrix [][]string) bool {
|
||||
initCols := len(strmatrix[0])
|
||||
|
||||
if initCols == 0 || len(strmatrix) == 0 {
|
||||
log.Printf("emptymatrix: we don't want those")
|
||||
return false
|
||||
}
|
||||
|
||||
for i, v := range strmatrix {
|
||||
cols := len(v)
|
||||
|
||||
if cols != initCols {
|
||||
log.Printf("notamatrix: all rows until now were of '%d' columns\noffending row: #%d, size: %d", initCols, i, cols)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func initMatrix(strmatrix [][]string) matrix {
|
||||
m := &matrix{}
|
||||
// we can now safely do this because at this point we have already checked
|
||||
// that strmatrix is a "valid" matrix.
|
||||
cols := len(strmatrix[0])
|
||||
rows := len(strmatrix)
|
||||
|
||||
// prealloc, when the size is known, gosimple is wrong here.
|
||||
m.rows = make([][]int, rows, rows) //nolint:gosimple
|
||||
for i := range strmatrix {
|
||||
// prealloc, when the size is known, gosimple is wrong here.
|
||||
m.rows[i] = make([]int, cols, cols) //nolint:gosimple
|
||||
}
|
||||
|
||||
return *m
|
||||
}
|
||||
|
||||
// convertMatrix attempts to convert the whole string matrix to an int matrix.
|
||||
func convertMatrix(strmatrix [][]string) matrix {
|
||||
if !isNonEmptyMatrix(strmatrix) {
|
||||
log.Fatalln("bailing...")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
m := initMatrix(strmatrix)
|
||||
|
||||
for i, v := range strmatrix {
|
||||
m.rows[i] = rowtoi(v)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// traverseMatrix traverses the given matrix in such a manner as to accumulate
|
||||
// the smallest possible sum. allowed movements are down and to the right.
|
||||
func traverseMatrixMinSumPath(m matrix) { //nolint:unparam
|
||||
// ad unparam: m will be used shortly.
|
||||
start := time.Now()
|
||||
|
||||
log.Printf("traversing the matrix took: %s", time.Since(start))
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2022 wanderer <wanderer at dotya.ml>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var csvreader *csv.Reader
|
||||
|
||||
// readFile tries to open the file passed in func argument and returns a
|
||||
// *csvreader if the file could be open.
|
||||
func readFile(fname string) csv.Reader {
|
||||
f, err := os.Open(fname)
|
||||
if err != nil {
|
||||
log.Fatalf("error reading file %s, bailing...\n", fname)
|
||||
}
|
||||
|
||||
csvreader = csv.NewReader(f)
|
||||
|
||||
return *csvreader
|
||||
}
|
||||
|
||||
// readArg returns a *csvreader that reads from the passed arg.
|
||||
func readArg(arg string) csv.Reader {
|
||||
if arg == "" {
|
||||
log.Fatalf("the arg is empty, bailing...\n")
|
||||
}
|
||||
|
||||
return *csv.NewReader(strings.NewReader(arg))
|
||||
}
|
Loading…
Reference in New Issue