266 lines
5.4 KiB
Go
266 lines
5.4 KiB
Go
|
// For the Matrix exercise in Go you have to do a few things not mentioned
|
||
|
// in the README.
|
||
|
//
|
||
|
// 1. You must implement a constructor and methods Rows() and Cols() as
|
||
|
// described in the README, but Rows() and Cols must return results that
|
||
|
// are independent from the original matrix. That is, you should be able
|
||
|
// to do as you please with the results without affecting the matrix.
|
||
|
//
|
||
|
// 2. You must implement a method Set(row, col, val) for setting a matrix
|
||
|
// element.
|
||
|
//
|
||
|
// 3. As usual in Go, you must detect and return error conditions.
|
||
|
|
||
|
package matrix
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
var tests = []struct {
|
||
|
in string
|
||
|
ok bool
|
||
|
rows [][]int
|
||
|
cols [][]int
|
||
|
}{
|
||
|
{"1 2\n10 20",
|
||
|
true,
|
||
|
[][]int{
|
||
|
{1, 2},
|
||
|
{10, 20},
|
||
|
},
|
||
|
[][]int{
|
||
|
{1, 10},
|
||
|
{2, 20},
|
||
|
},
|
||
|
},
|
||
|
{"9 7\n8 6",
|
||
|
true,
|
||
|
[][]int{
|
||
|
{9, 7},
|
||
|
{8, 6},
|
||
|
},
|
||
|
[][]int{
|
||
|
{9, 8},
|
||
|
{7, 6},
|
||
|
},
|
||
|
},
|
||
|
{"9 8 7\n19 18 17",
|
||
|
true,
|
||
|
[][]int{
|
||
|
{9, 8, 7},
|
||
|
{19, 18, 17},
|
||
|
},
|
||
|
[][]int{
|
||
|
{9, 19},
|
||
|
{8, 18},
|
||
|
{7, 17},
|
||
|
},
|
||
|
},
|
||
|
{"1 4 9\n16 25 36",
|
||
|
true,
|
||
|
[][]int{
|
||
|
{1, 4, 9},
|
||
|
{16, 25, 36},
|
||
|
},
|
||
|
[][]int{
|
||
|
{1, 16},
|
||
|
{4, 25},
|
||
|
{9, 36},
|
||
|
},
|
||
|
},
|
||
|
{"1 2 3\n4 5 6\n7 8 9\n 8 7 6",
|
||
|
true,
|
||
|
[][]int{
|
||
|
{1, 2, 3},
|
||
|
{4, 5, 6},
|
||
|
{7, 8, 9},
|
||
|
{8, 7, 6},
|
||
|
},
|
||
|
[][]int{
|
||
|
{1, 4, 7, 8},
|
||
|
{2, 5, 8, 7},
|
||
|
{3, 6, 9, 6},
|
||
|
},
|
||
|
},
|
||
|
{"89 1903 3\n18 3 1\n9 4 800",
|
||
|
true,
|
||
|
[][]int{
|
||
|
{89, 1903, 3},
|
||
|
{18, 3, 1},
|
||
|
{9, 4, 800},
|
||
|
},
|
||
|
[][]int{
|
||
|
{89, 18, 9},
|
||
|
{1903, 3, 4},
|
||
|
{3, 1, 800},
|
||
|
},
|
||
|
},
|
||
|
{"1 2 3", // valid, 1 row, 3 columns
|
||
|
true,
|
||
|
[][]int{
|
||
|
{1, 2, 3},
|
||
|
},
|
||
|
[][]int{
|
||
|
{1},
|
||
|
{2},
|
||
|
{3},
|
||
|
},
|
||
|
},
|
||
|
{"1\n2\n3", // valid, 3 rows, 1 column
|
||
|
true,
|
||
|
[][]int{
|
||
|
{1},
|
||
|
{2},
|
||
|
{3},
|
||
|
},
|
||
|
[][]int{
|
||
|
{1, 2, 3},
|
||
|
},
|
||
|
},
|
||
|
{"0", // valid, 1 row, 1 column
|
||
|
true,
|
||
|
[][]int{
|
||
|
{0},
|
||
|
},
|
||
|
[][]int{
|
||
|
{0},
|
||
|
},
|
||
|
},
|
||
|
{"9223372036854775808", false, nil, nil}, // overflows int64
|
||
|
{"1 2\n10 20 30", false, nil, nil}, // uneven rows
|
||
|
{"\n3 4\n5 6", false, nil, nil}, // first row empty
|
||
|
{"1 2\n\n5 6", false, nil, nil}, // middle row empty
|
||
|
{"1 2\n3 4\n", false, nil, nil}, // last row empty
|
||
|
{"2.7", false, nil, nil}, // non-int
|
||
|
{"cat", false, nil, nil}, // non-numeric
|
||
|
// undefined
|
||
|
// {"\n\n", // valid?, 3 rows, 0 columns
|
||
|
// {"", // valid?, 0 rows, 0 columns
|
||
|
}
|
||
|
|
||
|
func TestNew(t *testing.T) {
|
||
|
for _, test := range tests {
|
||
|
m, err := New(test.in)
|
||
|
switch {
|
||
|
case err != nil:
|
||
|
if test.ok {
|
||
|
t.Fatalf("New(%q) returned error %q. Error not expected",
|
||
|
test.in, err)
|
||
|
}
|
||
|
case !test.ok:
|
||
|
t.Fatalf("New(%q) = %v, %v. Expected non-nil error.",
|
||
|
test.in, m, err)
|
||
|
case m == nil:
|
||
|
t.Fatalf("New(%q) = %v, want non-nil *Matrix",
|
||
|
test.in, m)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestRows(t *testing.T) {
|
||
|
for _, test := range tests {
|
||
|
if !test.ok {
|
||
|
continue
|
||
|
}
|
||
|
m, err := New(test.in)
|
||
|
if err != nil {
|
||
|
t.Skip("Need working New for TestRows")
|
||
|
}
|
||
|
r := m.Rows()
|
||
|
if len(r) == 0 && len(test.rows) == 0 {
|
||
|
continue // agreement, and nothing more to test
|
||
|
}
|
||
|
if !reflect.DeepEqual(r, test.rows) {
|
||
|
t.Fatalf("New(%q).Rows() = %v, want %v", test.in, r, test.rows)
|
||
|
}
|
||
|
if len(r[0]) == 0 {
|
||
|
continue // not currently in test data, but anyway
|
||
|
}
|
||
|
r[0][0]++
|
||
|
if !reflect.DeepEqual(m.Rows(), test.rows) {
|
||
|
t.Fatalf("Matrix.Rows() returned slice based on Matrix " +
|
||
|
"representation. Want independent copy of element data.")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestCols(t *testing.T) {
|
||
|
for _, test := range tests {
|
||
|
if !test.ok {
|
||
|
continue
|
||
|
}
|
||
|
m, err := New(test.in)
|
||
|
if err != nil {
|
||
|
t.Skip("Need working New for TestCols")
|
||
|
}
|
||
|
c := m.Cols()
|
||
|
if len(c) == 0 && len(test.cols) == 0 {
|
||
|
continue // agreement, and nothing more to test
|
||
|
}
|
||
|
if !reflect.DeepEqual(c, test.cols) {
|
||
|
t.Fatalf("New(%q).Cols() = %v, want %v", test.in, c, test.cols)
|
||
|
}
|
||
|
if len(c[0]) == 0 {
|
||
|
continue // not currently in test data, but anyway
|
||
|
}
|
||
|
c[0][0]++
|
||
|
if !reflect.DeepEqual(m.Cols(), test.cols) {
|
||
|
t.Fatalf("Matrix.Cols() returned slice based on Matrix " +
|
||
|
"representation. Want independent copy of element data.")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestSet(t *testing.T) {
|
||
|
s := "1 2 3\n4 5 6\n7 8 9"
|
||
|
m, err := New(s)
|
||
|
if err != nil {
|
||
|
t.Skip("Need working New for TestSet")
|
||
|
}
|
||
|
xr := [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
|
||
|
if !reflect.DeepEqual(m.Rows(), xr) {
|
||
|
t.Skip("Need working Rows for TestSet")
|
||
|
}
|
||
|
xc := [][]int{{1, 4, 7}, {2, 5, 8}, {3, 6, 9}}
|
||
|
if !reflect.DeepEqual(m.Cols(), xc) {
|
||
|
t.Skip("Need working Cols for TestSet")
|
||
|
}
|
||
|
// test each corner, each side, and an interior element
|
||
|
for r := 0; r < 3; r++ {
|
||
|
for c := 0; c < 3; c++ {
|
||
|
m, _ = New(s)
|
||
|
val := 10 + r*3 + c
|
||
|
if ok := m.Set(r, c, val); !ok {
|
||
|
t.Fatalf("Matrix(%q).Set(%d, %d, %d) returned !ok, want ok.",
|
||
|
s, r, c, val)
|
||
|
}
|
||
|
xr = [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
|
||
|
xc = [][]int{{1, 4, 7}, {2, 5, 8}, {3, 6, 9}}
|
||
|
xr[r][c] = val
|
||
|
xc[c][r] = val
|
||
|
if res := m.Rows(); !reflect.DeepEqual(res, xr) {
|
||
|
t.Fatalf("Matrix(%q).Set(%d, %d, %d), Rows() = %v, want %v",
|
||
|
s, r, c, val, res, xr)
|
||
|
}
|
||
|
if res := m.Cols(); !reflect.DeepEqual(res, xc) {
|
||
|
t.Fatalf("Matrix(%q).Set(%d, %d, %d), Cols() = %v, want %v",
|
||
|
s, r, c, val, res, xc)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// test 1 and 2 off each corner and side
|
||
|
m, _ = New(s)
|
||
|
for _, r := range []int{-2, -1, 0, 3, 4} {
|
||
|
for _, c := range []int{-2, -1, 0, 3, 4} {
|
||
|
if r == 0 && c == 0 {
|
||
|
continue
|
||
|
}
|
||
|
if ok := m.Set(r, c, 0); ok {
|
||
|
t.Fatalf("Matrix(%q).Set(%d, %d, 0) = ok, want !ok", s, r, c)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|