Updating the Repo

This commit is contained in:
2016-09-03 09:53:54 -05:00
parent ec45e6b2eb
commit 739f3c3e2b
21 changed files with 969 additions and 5 deletions

1
go/current Symbolic link
View File

@@ -0,0 +1 @@
matrix

53
go/grade-school/README.md Normal file
View File

@@ -0,0 +1,53 @@
# Grade School
Write a small archiving program that stores students' names along with the grade that they are in.
In the end, you should be able to:
- Add a student's name to the roster for a grade
- "Add Jim to grade 2."
- "OK."
- Get a list of all students enrolled in a grade
- "Which students are in grade 2?"
- "We've only got Jim just now."
- Get a sorted list of all students in all grades. Grades should sort
as 1, 2, 3, etc., and students within a grade should be sorted
alphabetically by name.
- "Who all is enrolled in school right now?"
- "Grade 1: Anna, Barb, and Charlie. Grade 2: Alex, Peter, and Zoe.
Grade 3…"
Note that all our students only have one name. (It's a small town, what
do you want?)
## For bonus points
Did you get the tests passing and the code clean? If you want to, these
are some additional things you could try:
- If you're working in a language with mutable data structures and your
implementation allows outside code to mutate the school's internal DB
directly, see if you can prevent this. Feel free to introduce additional
tests.
Then please share your thoughts in a comment on the submission. Did this
experiment make the code better? Worse? Did you learn anything from it?
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
A pairing session with Phil Battos at gSchool [http://gschool.it](http://gschool.it)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

View File

@@ -0,0 +1,173 @@
// API:
//
// type Grade struct {
// int, []string
// }
//
// type School
// func New() *School
// func (s *School) Add(string, int)
// func (s *School) Grade(int) []string
// func (s *School) Enrollment() []Grade
package school
import (
"fmt"
"math/rand"
"strconv"
"testing"
)
func TestNewSchoolIsEmpty(t *testing.T) {
if len(New().Enrollment()) != 0 {
t.Error("New school not empty")
}
}
func list(e []Grade) (s string) {
for _, l := range e {
s += fmt.Sprintln(l)
}
return s
}
func TestAddStudent(t *testing.T) {
exp := list([]Grade{{2, []string{"Aimee"}}})
s := New()
s.Add("Aimee", 2)
got := list(s.Enrollment())
if got != exp {
t.Errorf(`Add Aimee level 2, got
%sexpected:
%s`, got, exp)
}
}
func TestAddMoreSameGrade(t *testing.T) {
exp := list([]Grade{{2, []string{"Blair James Paul"}}})
s := New()
s.Add("Blair", 2)
s.Add("James", 2)
s.Add("Paul", 2)
got := list(s.Enrollment())
if got != exp {
t.Errorf(`Add more same grade, got
%sexpected:
%s`, got, exp)
}
}
func TestAddDifferentGrades(t *testing.T) {
exp := list([]Grade{
{3, []string{"Chelsea"}},
{7, []string{"Logan"}},
})
s := New()
s.Add("Chelsea", 3)
s.Add("Logan", 7)
got := list(s.Enrollment())
if got != exp {
t.Errorf(`Add different grades, got
%sexpected:
%s`, got, exp)
}
}
func TestGetGrade(t *testing.T) {
exp := []string{"Bradley", "Franklin"}
s := New()
s.Add("Bradley", 5)
s.Add("Franklin", 5)
s.Add("Jeff", 1)
got := s.Grade(5)
if len(got) == len(exp) {
if got[0] == exp[0] && got[1] == exp[1] ||
got[0] == exp[1] && got[1] == exp[0] { // accept out of order
return
}
}
t.Errorf(`Get grade, got
%v
expected
%v`, got, exp)
}
func TestNonExistantGrade(t *testing.T) {
s := New()
got := s.Grade(1)
if len(got) != 0 {
t.Errorf(`Get non-existant grade, got
%v
expected
[]`, got)
}
}
func TestSortedEnrollment(t *testing.T) {
exp := list([]Grade{
{3, []string{"Kyle"}},
{4, []string{"Christopher Jennifer"}},
{6, []string{"Kareem"}},
})
s := New()
s.Add("Jennifer", 4)
s.Add("Kareem", 6)
s.Add("Christopher", 4)
s.Add("Kyle", 3)
got := list(s.Enrollment())
if got != exp {
t.Errorf(`Sorted enrollment, got
%sexpected:
%s`, got, exp)
}
}
const (
minLevel = 1
maxLevel = 9
enrollment = 400
)
func BenchmarkAddStudents(b *testing.B) {
const pool = 1e6 // pool of students
names := make([]string, pool)
levels := make([]int, pool)
for i := range names {
names[i] = strconv.Itoa(rand.Intn(1e5))
levels[i] = minLevel + rand.Intn(maxLevel-minLevel+1)
}
p := 0
b.ResetTimer()
for i := 0; i < b.N; i++ {
// bench combined time to create a school and add
// a number of students, drawn from a pool of students
s := New()
for t := 0; t < enrollment; t++ {
s.Add(names[p], levels[p])
p = (p + 1) % pool
}
}
}
func BenchmarkEnrollment(b *testing.B) {
const pool = 1000 // pool of schools
ss := make([]*School, pool)
for i := range ss {
s := New()
for t := 0; t < enrollment; t++ {
s.Add(
strconv.Itoa(rand.Intn(1e5)),
minLevel+rand.Intn(maxLevel-minLevel+1))
}
ss[i] = s
}
p := 0
b.ResetTimer()
for i := 0; i < b.N; i++ {
// bench time to get enrollment of a full school,
// averaged over a pool of schools.
ss[p].Enrollment()
p = (p + 1) % pool
}
}

53
go/grade-school/school.go Normal file
View File

@@ -0,0 +1,53 @@
package school
import "sort"
// A Grade is just the grade number and a list of students
type Grade struct {
Num int
Students []string
}
// AddStudent adds a student name to a grades roster
func (g *Grade) AddStudent(name string) {
g.Students = append(g.Students, name)
}
// School is just a collection of Grades
type School struct {
grades map[int]Grade
}
// New returns a new School object
func New() *School {
return &School{
grades: make(map[int]Grade),
}
}
// Add add student 'name' to grade 'grade'
func (s *School) Add(name string, grade int) {
g := s.grades[grade]
g.Num = grade
g.AddStudent(name)
s.grades[grade] = g
}
// Grade returns a sorted list of all students in 'grade'
func (s *School) Grade(grade int) []string {
g := s.grades[grade]
sort.Strings(g.Students)
return g.Students
}
// Enrollment returns the full school's enrollment, sorted by grade then name
func (s *School) Enrollment() []Grade {
var ret []Grade
for k := 1; k <= 12; k++ {
grRoster := s.Grade(k)
if len(grRoster) > 0 {
ret = append(ret, Grade{Num: k, Students: grRoster})
}
}
return ret
}

56
go/matrix/README.md Normal file
View File

@@ -0,0 +1,56 @@
# Matrix
Write a program that, given a string representing a matrix of numbers, can return the rows and columns of that matrix.
So given a string with embedded newlines like:
> 9 8 7
> 5 3 2
> 6 6 7
representing this matrix:
```plain
0 1 2
|---------
0 | 9 8 7
1 | 5 3 2
2 | 6 6 7
```
your code should be able to spit out:
- A list of the rows, reading each row left-to-right while moving
top-to-bottom across the rows,
- A list of the columns, reading each column top-to-bottom while moving
from left-to-right.
The rows for our example matrix:
- 9, 8, 7
- 5, 3, 2
- 6, 6, 7
And its columns:
- 9, 5, 6
- 8, 3, 6
- 7, 2, 7
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
Warmup to the `saddle-points` warmup. [http://jumpstartlab.com](http://jumpstartlab.com)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

265
go/matrix/matrix_test.go Normal file
View File

@@ -0,0 +1,265 @@
// 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)
}
}
}
}

View File

@@ -0,0 +1,45 @@
# Nucleotide Count
Given a DNA string, compute how many times each nucleotide occurs in the string.
DNA is represented by an alphabet of the following symbols: 'A', 'C',
'G', and 'T'.
Each symbol represents a nucleotide, which is a fancy name for the
particular molecules that happen to make up a large part of DNA.
Shortest intro to biochemistry EVAR:
- twigs are to birds nests as
- nucleotides are to DNA and RNA as
- amino acids are to proteins as
- sugar is to starch as
- oh crap lipids
I'm not going to talk about lipids because they're crazy complex.
So back to nucleotides.
DNA contains four types of them: adenine (`A`), cytosine (`C`), guanine
(`G`), and thymine (`T`).
RNA contains a slightly different set of nucleotides, but we don't care
about that for now.
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
The Calculating DNA Nucleotides_problem at Rosalind [http://rosalind.info/problems/dna/](http://rosalind.info/problems/dna/)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

View File

@@ -0,0 +1,38 @@
package dna
import (
"errors"
"strings"
)
// Histogram is just a map
type Histogram map[byte]int
// DNAProc is a struct that holds a dna strand
type DNAProc struct {
strand string
}
// DNA is the function that creates DNAProcs
func DNA(st string) *DNAProc {
return &DNAProc{strand: st}
}
// Count takes a nucleotide byte and returns how many there are
// or an error if it's an invalid nucleotide
func (d *DNAProc) Count(n byte) (int, error) {
if n != 'A' && n != 'C' && n != 'G' && n != 'T' {
return 0, errors.New("Invalid Nucleotide " + string(n))
}
return strings.Count(d.strand, string(n)), nil
}
// Counts returns a Histogram of all nucleotide counts
func (d *DNAProc) Counts() Histogram {
h := make(Histogram)
h['A'], _ = d.Count('A')
h['C'], _ = d.Count('C')
h['G'], _ = d.Count('G')
h['T'], _ = d.Count('T')
return h
}

View File

@@ -0,0 +1,108 @@
package dna
import "testing"
func (h Histogram) Equal(o Histogram) bool {
return h.sameLength(o) && h.sameMappings(o)
}
func (h Histogram) sameLength(o Histogram) bool {
return len(h) == len(o)
}
func (h Histogram) sameMappings(o Histogram) (res bool) {
res = true
for k := range h {
if h[k] != o[k] {
res = false
}
}
return
}
var tallyTests = []struct {
strand string
nucleotide byte
expected int
}{
{"", 'A', 0},
{"ACT", 'G', 0},
{"CCCCC", 'C', 5},
{"GGGGGTAACCCGG", 'T', 1},
}
func TestNucleotideCounts(t *testing.T) {
for _, tt := range tallyTests {
dna := DNA(tt.strand)
count, _ := dna.Count(tt.nucleotide)
if count != tt.expected {
t.Fatalf("Got \"%v\", expected \"%v\"", count, tt.expected)
}
}
}
func TestHasErrorForInvalidNucleotides(t *testing.T) {
dna := DNA("GATTACA")
count, err := dna.Count('X')
if count != 0 {
t.Fatalf("Got \"%v\", expected \"%v\"", count, 0)
}
if err == nil {
t.Fatalf("X is an invalid nucleotide, but no error was raised")
}
}
// In most cases, this test is pointless.
// Very occasionally it matters.
// Just roll with it.
func TestCountingDoesntChangeCount(t *testing.T) {
dna := DNA("CGATTGGG")
dna.Count('T')
count, _ := dna.Count('T')
if count != 2 {
t.Fatalf("Got \"%v\", expected \"%v\"", count, 2)
}
}
type histogramTest struct {
strand string
expected Histogram
}
var histogramTests = []histogramTest{
{
"",
Histogram{'A': 0, 'C': 0, 'T': 0, 'G': 0},
},
{
"GGGGGGGG",
Histogram{'A': 0, 'C': 0, 'T': 0, 'G': 8},
},
{
"AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC",
Histogram{'A': 20, 'C': 12, 'T': 21, 'G': 17},
},
}
func TestSequenceHistograms(t *testing.T) {
for _, tt := range histogramTests {
dna := DNA(tt.strand)
if !dna.Counts().Equal(tt.expected) {
t.Fatalf("DNA{ \"%v\" }: Got \"%v\", expected \"%v\"", tt.strand, dna.Counts(), tt.expected)
}
}
}
func BenchmarkSequenceHistograms(b *testing.B) {
b.StopTimer()
for _, tt := range histogramTests {
for i := 0; i < b.N; i++ {
dna := DNA(tt.strand)
b.StartTimer()
dna.Counts()
b.StopTimer()
}
}
}

41
go/wordy/wordy.go Normal file
View File

@@ -0,0 +1,41 @@
package wordy
import (
"strconv"
"strings"
)
// Answer parses a simple word problem and returns the result
// or false if it wasn't valid
func Answer(inp string) (int, bool) {
var ret int
var operation string
var didOperation bool
words := strings.Fields(inp)
for i := range words {
tstWord := strings.Replace(words[i], "?", "", -1)
if v, err := strconv.Atoi(tstWord); err == nil {
switch operation {
case "":
ret = v
case "plus":
ret += v
didOperation = true
case "minus":
ret -= v
didOperation = true
case "multiplied":
ret *= v
didOperation = true
case "divided":
ret /= v
didOperation = true
}
} else {
if words[i] == "plus" || words[i] == "minus" || words[i] == "multiplied" || words[i] == "divided" {
operation = words[i]
}
}
}
return ret, didOperation
}