호두나무 공방/Exercism in Elixir

House - Exercism in Elixir

2022. 7. 19. 22:00

문제 보기

절 수가 늘어날수록 길이가 길어지는 (그런데 이제 길어지는 형식이 정해져 있는) 노래가사를 만드는 문제였다. 어떻게 하면 텍스트 양을 줄일 수 있을까 고민하다가, 절에 따라 달라지는 부분을 모듈 속성으로 분리하고 This isthat 을 공통으로 쓰는 식으로 작성했다.

defmodule House do
  @items [
    %{subject: "the house that Jack built", verb: "lay in"},
    %{subject: "the malt", verb: "ate"},
    %{subject: "the rat", verb: "killed"},
    %{subject: "the cat", verb: "worried"},
    %{subject: "the dog", verb: "tossed"},
    %{subject: "the cow with the crumpled horn", verb: "milked"},
    %{subject: "the maiden all forlorn", verb: "kissed"},
    %{subject: "the man all tattered and torn", verb: "married"},
    %{subject: "the priest all shaven and shorn", verb: "woke"},
    %{subject: "the rooster that crowed in the morn", verb: "kept"},
    %{subject: "the farmer sowing his corn", verb: "belonged to"},
    %{subject: "the horse and the hound and the horn", verb: ""},
  ]

  @doc """
  Return verses of the nursery rhyme 'This is the House that Jack Built'.
  """
  @spec recite(start :: integer, stop :: integer) :: String.t()
  def recite(start, stop) do
    start..stop    
    |> Enum.map(fn i ->
      Enum.slice(@items, 0, i)
      |> Enum.reverse()
      |> Enum.with_index()
      |> Enum.reduce("This is", fn
        {item, 0}, acc ->
          acc <> " " <> item.subject
        {item, _}, acc ->
          acc <> " that #{item.verb} #{item.subject}"
      end)
      |> Kernel.<>(".\n")
    end)
    |> Enum.join("")
  end
end