summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-11-11 16:47:38 +0100
committerDimitri Sokolyuk <demon@dim13.org>2016-11-11 16:47:38 +0100
commit366d79482f4bb1cb9d93e8dbf620c83821870b63 (patch)
treea7ceccfe0225973cce10f2048f401903ced9121e
parentb1f583939a93886813088ebba1d0e996688437c3 (diff)
Add Grade School
-rw-r--r--go/grade-school/README.md53
-rw-r--r--go/grade-school/grade_school_test.go173
2 files changed, 226 insertions, 0 deletions
diff --git a/go/grade-school/README.md b/go/grade-school/README.md
new file mode 100644
index 0000000..5e7ad69
--- /dev/null
+++ b/go/grade-school/README.md
@@ -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.
+
diff --git a/go/grade-school/grade_school_test.go b/go/grade-school/grade_school_test.go
new file mode 100644
index 0000000..a827baf
--- /dev/null
+++ b/go/grade-school/grade_school_test.go
@@ -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
+ }
+}