Updating the Repo
This commit is contained in:
53
go/grade-school/README.md
Normal file
53
go/grade-school/README.md
Normal 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.
|
||||
|
173
go/grade-school/grade_school_test.go
Normal file
173
go/grade-school/grade_school_test.go
Normal 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
53
go/grade-school/school.go
Normal 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
|
||||
}
|
Reference in New Issue
Block a user