diff --git a/config.json b/config.json index cb944adc..62bae0dd 100644 --- a/config.json +++ b/config.json @@ -854,6 +854,14 @@ "practices": [], "prerequisites": [], "difficulty": 2 + }, + { + "slug": "grade-school", + "name": "Grade School", + "uuid": "e5ab14bd-9eeb-4c63-8143-55e1e56b4ac1", + "practices": [], + "prerequisites": [], + "difficulty": 5 } ] }, diff --git a/exercises/practice/grade-school/.docs/instructions.md b/exercises/practice/grade-school/.docs/instructions.md new file mode 100644 index 00000000..9a63e398 --- /dev/null +++ b/exercises/practice/grade-school/.docs/instructions.md @@ -0,0 +1,21 @@ +# Instructions + +Given students' names along with the grade that they are in, create a roster for the school. + +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?" + - "Let me think. + We have Anna, Barb, and Charlie in grade 1, Alex, Peter, and Zoe in grade 2 and Jim in grade 5. + So the answer is: Anna, Barb, Charlie, Alex, Peter, Zoe and Jim" + +Note that all our students only have one name (It's a small town, what do you want?) and each student cannot be added more than once to a grade or the roster. +In fact, when a test attempts to add the same student more than once, your implementation should indicate that this is incorrect. diff --git a/exercises/practice/grade-school/.meta/config.json b/exercises/practice/grade-school/.meta/config.json new file mode 100644 index 00000000..a11f7a13 --- /dev/null +++ b/exercises/practice/grade-school/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "kmarker1101" + ], + "files": { + "solution": [ + "grade-school.el" + ], + "test": [ + "grade-school-test.el" + ], + "example": [ + ".meta/example.el" + ] + }, + "blurb": "Given students' names along with the grade that they are in, create a roster for the school.", + "source": "A pairing session with Phil Battos at gSchool" +} diff --git a/exercises/practice/grade-school/.meta/example.el b/exercises/practice/grade-school/.meta/example.el new file mode 100644 index 00000000..765ab6d7 --- /dev/null +++ b/exercises/practice/grade-school/.meta/example.el @@ -0,0 +1,36 @@ +;;; grade-school.el --- Grade School (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + + +(require 'cl-lib) + +(cl-defstruct school (roster (make-hash-table :test 'equal))) + +(defun add (school name grade) + (let ((current-roster (school-roster school))) + (if (cl-loop for g being the hash-keys of current-roster + thereis (member name (gethash g current-roster))) + nil + (puthash grade (sort (cons name (gethash grade current-roster)) #'string<) current-roster) + t))) + +(defun roster (school) + (let ((grades-and-names (list))) + (maphash (lambda (grade names) (push (cons grade names) grades-and-names)) + (school-roster school)) + (apply #'append + (mapcar #'cdr + (sort grades-and-names (lambda (a b) (< (car a) (car b)))))))) + +(defun grade (school grade) + (gethash grade (school-roster school))) + +(defun set-grade (school grade newval) + (puthash grade (sort newval #'string<) (school-roster school))) + + +(provide 'grade-school) +;;; grade-school.el ends here diff --git a/exercises/practice/grade-school/.meta/tests.toml b/exercises/practice/grade-school/.meta/tests.toml new file mode 100644 index 00000000..50c9e2e5 --- /dev/null +++ b/exercises/practice/grade-school/.meta/tests.toml @@ -0,0 +1,86 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# 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 = "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" + +[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 = "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" + +[c7ec1c5e-9ab7-4d3b-be5c-29f2f7a237c5] +description = "Student not added to multiple grades in the roster" +reimplements = "6a03b61e-1211-4783-a3cc-fc7f773fba3f" + +[d9af4f19-1ba1-48e7-94d0-dabda4e5aba6] +description = "Students are sorted by grades in the roster" + +[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 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" diff --git a/exercises/practice/grade-school/grade-school-test.el b/exercises/practice/grade-school/grade-school-test.el new file mode 100644 index 00000000..e173b439 --- /dev/null +++ b/exercises/practice/grade-school/grade-school-test.el @@ -0,0 +1,170 @@ +;;; grade-school-test.el --- Grade School (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + + +(load-file "grade-school.el") +(declare-function roster "grade-school.el" (students)) +(declare-function add "grade-school.el" (students)) +(declare-function grade "grade-school.el" (desired-grade students)) + + +(ert-deftest roster-is-empty-when-no-student-is-added () + (let ((test-school (make-school))) + (should (equal (roster test-school) '())))) + + +(ert-deftest add-a-student () + (let ((test-school (make-school))) + (should (add test-school "Aimee" 2)))) + + +(ert-deftest student-is-added-to-the-roster () + (let ((test-school (make-school))) + (add test-school "Aimee" 2) + (should (equal (roster test-school) '("Aimee"))))) + + +(ert-deftest adding-multiple-students-in-the-same-grade-in-the-roster () + (let ((test-school (make-school))) + (should (add test-school "Blair" 2)) + (should (add test-school "James" 2)) + (should (add test-school "Paul" 2)))) + + +(ert-deftest multiple-students-in-the-same-grade-are-added-to-the-roster () + (let ((test-school (make-school))) + (add test-school "Blair" 2) + (add test-school "James" 2) + (add test-school "Paul" 2) + (should (equal (roster test-school) '("Blair" "James" "Paul"))))) + + +(ert-deftest cannot-add-student-to-same-grade-in-the-roster-more-than-once () + (let ((test-school (make-school))) + (should (add test-school "Blair" 2)) + (should (add test-school "James" 2)) + (should-not (add test-school "James" 2)) + (should (add test-school "Paul" 2)))) + + +(ert-deftest student-not-added-to-same-grade-in-the-roster-more-than-once () + (let ((test-school (make-school))) + (add test-school "Blair" 2) + (add test-school "James" 2) + (add test-school "James" 2) + (add test-school "Paul" 2) + (should (equal (roster test-school) '("Blair" "James" "Paul"))))) + + +(ert-deftest adding-students-in-multiple-grades () + (let ((test-school (make-school))) + (should (add test-school "Chelsea" 3)) + (should (add test-school "Loagan" 7)))) + + +(ert-deftest students-in-multiple-grades-are-added-to-the-roster () + (let ((test-school (make-school))) + (add test-school "Chelsea" 3) + (add test-school "Logan" 7) + (should (equal (roster test-school) '("Chelsea" "Logan"))))) + + +(ert-deftest cannot-add-same-student-to-multiple-grades-in-the-roster () + (let ((test-school (make-school))) + (should (add test-school "Blair" 2)) + (should (add test-school "James" 2)) + (should-not (add test-school "James" 3)) + (should (add test-school "Paul" 3)))) + + +(ert-deftest student-not-added-to-multiple-grades-in-the-roster () + (let ((test-school (make-school))) + (add test-school "Blair" 2) + (add test-school "James" 2) + (add test-school "James" 3) + (add test-school "Paul" 3) + (should (equal (roster test-school) '("Blair" "James" "Paul"))))) + + +(ert-deftest students-are-sorted-by-grades-in-the-roster () + (let ((test-school (make-school))) + (add test-school "Jim" 3) + (add test-school "Peter" 2) + (add test-school "Anna" 1) + (should (equal (roster test-school) '("Anna" "Peter" "Jim"))))) + + +(ert-deftest students-are-sorted-by-name-in-the-roster () + (let ((test-school (make-school))) + (add test-school "Peter" 2) + (add test-school "Zoe" 2) + (add test-school "Alex" 2) + (should (equal (roster test-school) '("Alex" "Peter" "Zoe"))))) + + +(ert-deftest students-are-sorted-by-grades-and-then-by-name-in-the-roster () + (let ((test-school (make-school))) + (add test-school "Peter" 2) + (add test-school "Anna" 1) + (add test-school "Barb" 1) + (add test-school "Zoe" 2) + (add test-school "Alex" 2) + (add test-school "Jim" 3) + (add test-school "Charlie" 1) + (should (equal (roster test-school) '("Anna" "Barb" "Charlie" "Alex" "Peter" "Zoe" "Jim"))))) + + +(ert-deftest grade-is-empty-if-no-students-in-the-roster () + (let ((test-school (make-school))) + (should (equal (grade test-school 1) '())))) + + +(ert-deftest grade-is-empty-if-no-students-in-that-grade () + (let ((test-school (make-school))) + (add test-school "Peter" 2) + (add test-school "Zoe" 2) + (add test-school "Alex" 2) + (add test-school "Jim" 3) + (should (equal (grade test-school 1) '())))) + + +(ert-deftest student-not-added-to-same-grade-more-than-once () + (let ((test-school (make-school))) + (add test-school "Blair" 2) + (add test-school "James" 2) + (add test-school "James" 2) + (add test-school "Paul" 2) + (should (equal (grade test-school 2) '("Blair" "James" "Paul"))))) + + +(ert-deftest student-not-added-to-multiple-grades () + (let ((test-school (make-school))) + (add test-school "Blair" 2) + (add test-school "James" 2) + (add test-school "James" 3) + (add test-school "Paul" 3) + (should (equal (grade test-school 2) '("Blair" "James"))))) + + +(ert-deftest student-not-added-to-other-grade-for-multiple-grades () + (let ((test-school (make-school))) + (add test-school "Blair" 2) + (add test-school "James" 2) + (add test-school "James" 3) + (add test-school "Paul" 3) + (should (equal (grade test-school 3) '("Paul"))))) + + +(ert-deftest students-are-sorted-by-name-in-a-grade () + (let ((test-school (make-school))) + (add test-school "Franklin" 5) + (add test-school "Bradley" 5) + (add test-school "Jeff" 1) + (should (equal (grade test-school 5) '("Bradley" "Franklin"))))) + + +(provide 'grade-school-test) +;;; grade-school-test.el ends here diff --git a/exercises/practice/grade-school/grade-school.el b/exercises/practice/grade-school/grade-school.el new file mode 100644 index 00000000..784cae79 --- /dev/null +++ b/exercises/practice/grade-school/grade-school.el @@ -0,0 +1,20 @@ +;;; grade-school.el --- Grade School (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + + +(defun roster (students) + (error "Delete this S-Expression and write your own implementation")) + +(defun add (students) + (error "Delete this S-Expression and write your own implementation")) + +(defun grade (desired-grade students) + (error "Delete this S-Expression and write your own implementation")) + + +(provide 'grade-school) +;;; grade-school.el ends here +