호두나무 공방/Exercism in Elixir

Grade School - Exercism in Elixir

2022. 7. 1. 22:06

문제 보기

적당한 자료구조를 선택하여 학생의 이름과 학년을 저장하고 조회하는 프로그램을 만드는 문제였다. 나는 %{학년 => [이름]} 구조의 맵을 선택했다.

graderoster 함수의 Enum.sort는 공통화할 수도 있었는데(roster에서 grade를 호출하게 한다거나), roster에서는 이름이 중요하지 학년이 중요한 것은 아니어서 학년에 의존하는 grade 함수가 맞지 않는 것 같아 그대로 중복을 허용하게 두었다.

defmodule School do
  @moduledoc """
  Simulate students in a school.

  Each student is in a grade.
  """

  @type school :: %{integer() => [String.t()]}

  @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(school, String.t(), integer) :: {:ok | :error, school}
  def add(school, name, grade) do
    if name in roster(school) do
      {:error, school}
    else
      {:ok, Map.update(school, grade, [name], fn l -> [name | l] end)}
    end
  end

  @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

  @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.flat_map(fn {_grade, names} -> Enum.sort(names) end)
  end
end