Skip to content

Sync: re-write grade-school #1050

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,8 @@
"name": "Grade School",
"uuid": "4e6d3ddf-b696-40dc-ba02-ed998e595be7",
"prerequisites": [
"atoms",
"tuples",
"lists",
"maps",
"enum"
Expand Down
1 change: 1 addition & 0 deletions exercises/practice/grade-school/.meta/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"devonestes",
"drueck",
"elasticdog",
"jiegillet",
"jinyeow",
"kytrinyx",
"lpil",
Expand Down
47 changes: 38 additions & 9 deletions exercises/practice/grade-school/.meta/example.ex
Original file line number Diff line number Diff line change
@@ -1,19 +1,48 @@
defmodule School do
def add(db, name, grade) do
if name in List.flatten(Map.values(db)) do
db
@moduledoc """
Simulate students in a school.

Each student is in a grade.
"""

@type school :: map

@doc """
Create a new, empty school.
"""
@spec new() :: school
def new(), do: %{}

@doc """
Add a student to a particular grade in school.
"""
@spec add(school, String.t(), integer) :: {:ok | :error, school}
def add(school, name, grade) do
if name in List.flatten(Map.values(school)) do
{:error, school}
else
Map.update(db, grade, [name], &[name | &1])
{:ok, Map.update(school, grade, [name], &[name | &1])}
end
end

def grade(db, grade) do
Map.get(db, grade, [])
@doc """
Return the names of the students in a particular grade, sorted alphabetically.
"""
@spec grade(school, integer) :: [String.t()]
def grade(school, grade) do
Map.get(school, grade, [])
|> Enum.sort()
end

def sort(db) do
db
|> Enum.map(fn {k, v} -> {k, Enum.sort(v)} end)
@doc """
Return the names of all the students in the school sorted by grade and name.
"""
@spec roster(school) :: [String.t()]
def roster(school) do
school
|> Enum.map(fn {grade, students} -> {grade, Enum.sort(students)} end)
|> Enum.sort()
|> Enum.map(fn {_grade, students} -> students end)
|> Enum.concat()
end
end
65 changes: 54 additions & 11 deletions exercises/practice/grade-school/.meta/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,78 @@
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[a3f0fb58-f240-4723-8ddc-e644666b85cc]
description = "Roster is empty when no student is added"

[9337267f-7793-4b90-9b4a-8e3978408824]
description = "Add a student"

[6d0a30e4-1b4e-472e-8e20-c41702125667]
description = "Adding a student adds them to the sorted roster"
description = "Student is added to the roster"

[73c3ca75-0c16-40d7-82f5-ed8fe17a8e4a]
description = "Adding multiple students in the same grade in the roster"

[233be705-dd58-4968-889d-fb3c7954c9cc]
description = "Multiple students in the same grade are added to the roster"

[87c871c1-6bde-4413-9c44-73d59a259d83]
description = "Cannot add student to same grade in the roster more than once"

[c125dab7-2a53-492f-a99a-56ad511940d8]
description = "A student can't be in two different grades"
include = false

[a0c7b9b8-0e89-47f8-8b4a-c50f885e79d1]
description = "A student can only be added to the same grade in the roster once"
include = false
reimplements = "c125dab7-2a53-492f-a99a-56ad511940d8"

[233be705-dd58-4968-889d-fb3c7954c9cc]
description = "Adding more students adds them to the sorted roster"
[d7982c4f-1602-49f6-a651-620f2614243a]
description = "Student not added to same grade in the roster more than once"
reimplements = "a0c7b9b8-0e89-47f8-8b4a-c50f885e79d1"

[e70d5d8f-43a9-41fd-94a4-1ea0fa338056]
description = "Adding students in multiple grades"

[75a51579-d1d7-407c-a2f8-2166e984e8ab]
description = "Adding students to different grades adds them to the same sorted roster"
description = "Students in multiple grades are added to the roster"

[7df542f1-57ce-433c-b249-ff77028ec479]
description = "Cannot add same student to multiple grades in the roster"

[6a03b61e-1211-4783-a3cc-fc7f773fba3f]
description = "A student cannot be added to more than one grade in the sorted roster"
include = false
reimplements = "c125dab7-2a53-492f-a99a-56ad511940d8"

[a3f0fb58-f240-4723-8ddc-e644666b85cc]
description = "Roster returns an empty list if there are no students enrolled"
[c7ec1c5e-9ab7-4d3b-be5c-29f2f7a237c5]
description = "Student not added to multiple grades in the roster"
reimplements = "6a03b61e-1211-4783-a3cc-fc7f773fba3f"

[180a8ff9-5b94-43fc-9db1-d46b4a8c93b6]
description = "Student names with grades are displayed in the same sorted roster"
[d9af4f19-1ba1-48e7-94d0-dabda4e5aba6]
description = "Students are sorted by grades in the roster"

[1bfbcef1-e4a3-49e8-8d22-f6f9f386187e]
description = "Grade returns the students in that grade in alphabetical order"
[d9fb5bea-f5aa-4524-9d61-c158d8906807]
description = "Students are sorted by name in the roster"

[180a8ff9-5b94-43fc-9db1-d46b4a8c93b6]
description = "Students are sorted by grades and then by name in the roster"

[5e67aa3c-a3c6-4407-a183-d8fe59cd1630]
description = "Grade returns an empty list if there are no students in that grade"
description = "Grade is empty if no students in the roster"

[1e0cf06b-26e0-4526-af2d-a2e2df6a51d6]
description = "Grade is empty if no students in that grade"

[2bfc697c-adf2-4b65-8d0f-c46e085f796e]
description = "Student not added to same grade more than once"

[66c8e141-68ab-4a04-a15a-c28bc07fe6b9]
description = "Student not added to multiple grades"

[c9c1fc2f-42e0-4d2c-b361-99271f03eda7]
description = "Student not added to other grade for multiple grades"

[1bfbcef1-e4a3-49e8-8d22-f6f9f386187e]
description = "Students are sorted by name in a grade"
25 changes: 17 additions & 8 deletions exercises/practice/grade-school/lib/school.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,33 @@ defmodule School do
Each student is in a grade.
"""

@type school :: any()

@doc """
Create a new, empty school.
"""
@spec new() :: school
def new() do
end

@doc """
Add a student to a particular grade in school.
"""
@spec add(map, String.t(), integer) :: map
def add(db, name, grade) do
@spec add(school, String.t(), integer) :: {:ok | :error, school}
def add(school, name, grade) do
end

@doc """
Return the names of the students in a particular grade.
Return the names of the students in a particular grade, sorted alphabetically.
"""
@spec grade(map, integer) :: [String.t()]
def grade(db, grade) do
@spec grade(school, integer) :: [String.t()]
def grade(school, grade) do
end

@doc """
Sorts the school by grade and name.
Return the names of all the students in the school sorted by grade and name.
"""
@spec sort(map) :: [{integer, [String.t()]}]
def sort(db) do
@spec roster(school) :: [String.t()]
def roster(school) do
end
end
161 changes: 103 additions & 58 deletions exercises/practice/grade-school/test/school_test.exs
Original file line number Diff line number Diff line change
@@ -1,88 +1,133 @@
defmodule SchoolTest do
use ExUnit.Case

@db %{}
def make_school_with_students(students) do
{results, school} =
Enum.reduce(students, {[], School.new()}, fn {student, grade}, {results, school} ->
{result, school} = School.add(school, student, grade)
{[result | results], school}
end)

{Enum.reverse(results), school}
end

test "add student" do
actual = School.add(@db, "Aimee", 2)
assert actual == %{2 => ["Aimee"]}
# @tag :pending
test "Roster is empty when no student is added" do
assert School.roster(School.new()) == []
end

test "a student can only be added to the same grade once" do
actual =
@db
|> School.add("Aimee", 2)
|> School.add("Aimee", 2)
@tag :pending
test "Add a student" do
{result, school} = School.add(School.new(), "Aimee", 2)

assert actual == %{2 => ["Aimee"]}
assert result == :ok
assert School.roster(school) == ["Aimee"]
end

test "a student cannot be added to more than one grade" do
actual =
@db
|> School.add("Aimee", 2)
|> School.add("Aimee", 1)
@tag :pending
test "Adding multiple students in the same grade in the roster" do
students = [{"Blair", 2}, {"James", 2}, {"Paul", 2}]
{results, school} = make_school_with_students(students)

assert actual == %{2 => ["Aimee"]}
assert results == [:ok, :ok, :ok]
assert School.roster(school) == ["Blair", "James", "Paul"]
end

@tag :pending
test "add more students in same class" do
actual =
@db
|> School.add("James", 2)
|> School.add("Blair", 2)
|> School.add("Paul", 2)

assert Enum.sort(actual[2]) == ["Blair", "James", "Paul"]
test "Cannot add student to same grade in the roster more than once" do
students = [{"Blair", 2}, {"James", 2}, {"James", 2}, {"Paul", 2}]
{results, school} = make_school_with_students(students)

assert results == [:ok, :ok, :error, :ok]
assert School.roster(school) == ["Blair", "James", "Paul"]
end

@tag :pending
test "add students to different grades" do
actual =
@db
|> School.add("Chelsea", 3)
|> School.add("Logan", 7)
test "Adding students in multiple grades" do
students = [{"Chelsea", 3}, {"Logan", 7}]
{results, school} = make_school_with_students(students)

assert actual == %{3 => ["Chelsea"], 7 => ["Logan"]}
assert results == [:ok, :ok]
assert School.roster(school) == ["Chelsea", "Logan"]
end

@tag :pending
test "get students in a grade" do
actual =
@db
|> School.add("Bradley", 5)
|> School.add("Franklin", 5)
|> School.add("Jeff", 1)
|> School.grade(5)

assert Enum.sort(actual) == ["Bradley", "Franklin"]
test "Cannot add same student to multiple grades in the roster" do
students = [{"Blair", 2}, {"James", 2}, {"James", 3}, {"Paul", 3}]
{results, school} = make_school_with_students(students)

assert results == [:ok, :ok, :error, :ok]
assert School.roster(school) == ["Blair", "James", "Paul"]
end

@tag :pending
test "get students in a non existent grade" do
assert [] == School.grade(@db, 1)
test "Students are sorted by grades in the roster" do
students = [{"Jim", 3}, {"Peter", 2}, {"Anna", 1}]
{_results, school} = make_school_with_students(students)

assert School.roster(school) == ["Anna", "Peter", "Jim"]
end

@tag :pending
test "sort school by grade and by student name" do
actual =
@db
|> School.add("Peter", 2)
|> School.add("Anna", 1)
|> School.add("Barb", 1)
|> School.add("Zoe", 2)
|> School.add("Alex", 2)
|> School.add("Jim", 3)
|> School.add("Charlie", 1)
|> School.sort()

expected = [
{1, ["Anna", "Barb", "Charlie"]},
{2, ["Alex", "Peter", "Zoe"]},
{3, ["Jim"]}
test "Students are sorted by name in the roster" do
students = [{"Peter", 2}, {"Zoe", 2}, {"Alex", 2}]
{_results, school} = make_school_with_students(students)

assert School.roster(school) == ["Alex", "Peter", "Zoe"]
end

@tag :pending
test "Students are sorted by grades and then by name in the roster" do
students = [
{"Peter", 2},
{"Anna", 1},
{"Barb", 1},
{"Zoe", 2},
{"Alex", 2},
{"Jim", 3},
{"Charlie", 1}
]

assert expected == actual
{_results, school} = make_school_with_students(students)

assert School.roster(school) == ["Anna", "Barb", "Charlie", "Alex", "Peter", "Zoe", "Jim"]
end

@tag :pending
test "Grade is empty if no students in the roster" do
assert School.grade(School.new(), 1) == []
end

@tag :pending
test "Grade is empty if no students in that grade" do
students = [{"Peter", 2}, {"Zoe", 2}, {"Alex", 2}, {"Jim", 3}]
{_results, school} = make_school_with_students(students)

assert School.grade(school, 1) == []
end

@tag :pending
test "Student not added to same grade more than once" do
students = [{"Blair", 2}, {"James", 2}, {"James", 2}, {"Paul", 2}]
{_results, school} = make_school_with_students(students)

assert School.roster(school) == ["Blair", "James", "Paul"]
end

@tag :pending
test "Student not added to multiple grades" do
students = [{"Blair", 2}, {"James", 2}, {"James", 3}, {"Paul", 3}]
{_results, school} = make_school_with_students(students)

assert School.grade(school, 2) == ["Blair", "James"]
assert School.grade(school, 3) == ["Paul"]
end

@tag :pending
test "Students are sorted by name in a grade" do
students = [{"Franklin", 5}, {"Bradley", 5}, {"Jeff", 1}]
{_results, school} = make_school_with_students(students)

assert School.grade(school, 5) == ["Bradley", "Franklin"]
end
end