Elixir
  • My Elixir journey
  • Why functional programming?
  • Exhort
    • 🗓️Day 22
    • 🗓️Day 21
    • 🗓️Day 20
    • 🗓️Day 19
    • 🗓️Day 18
    • 🗓️Day 17
    • 🗓️Day 16
    • 🗓️Day 15
    • 🗓️Day 14
  • Bits and pieces
    • Clean mix dependencies
    • Run tests automatically on save
    • Run tests and stop on first failure
    • How to remove Tailwind from a Phoenix project
Powered by GitBook
On this page
  • Exercises
  • Boutique Suggestions
  • Community Garden
  • Bread and Potions
  • Overall progress
  1. Exhort

Day 17

Wednesday, 24 August 2022 - Day 17 of Exhort August 2022 - Exercism (My Elixir Journey)

PreviousDay 18NextDay 16

Last updated 2 years ago

Exercises

Boutique Suggestions

|

Solution

Expand to see code (spoiler alert)
defmodule BoutiqueSuggestions do
  def get_combinations(tops, bottoms, options \\ []) do
    mp = Keyword.get(options, :maximum_price, 100.0)

    for x <- tops,
        y <- bottoms,
        x.base_color != y.base_color and x.price + y.price <= mp do
      {x, y}
    end
  end
end

Notes

Community Garden

|

Solution

Expand to see code (spoiler alert)
defmodule Plot do
  @enforce_keys [:plot_id, :registered_to]
  defstruct [:plot_id, :registered_to]
end

defmodule CommunityGarden do
  @spec start(Keyword.t()) :: tuple()
  def start(opts \\ []) do
    Agent.start(fn -> [] end, opts)
  end

  @spec list_registrations(pid()) :: list(Plot)
  def list_registrations(pid) do
    Agent.get(pid, fn state -> state end)
  end

  @spec register(pid(), String.t()) :: Plot
  def register(pid, register_to) do
    Agent.update(pid, fn state ->
      [%Plot{plot_id: get_next_id(state), registered_to: register_to} | state]
    end)

    Agent.get(pid, fn state ->
      [head | _tail] = state
      head
    end)
  end

  defp get_next_id([]), do: 1
  defp get_next_id(plots), do: Enum.sort_by(plots, & &1.plot_id)

  @spec release(pid(), integer()) :: :ok
  def release(pid, plot_id) do
    Agent.update(pid, fn state ->
      Enum.filter(state, fn plot -> plot.plot_id != plot_id end)
    end)
  end

  @spec get_registration(pid(), integer()) :: tuple() | Plot
  def get_registration(pid, plot_id) do
    plot =
      Agent.get(pid, fn state ->
        Enum.find(state, nil, fn plot -> plot.plot_id == plot_id end)
      end)

    cond do
      plot == nil -> {:not_found, "plot is unregistered"}
      true -> plot
    end
  end
end

Notes

Bread and Potions

Solution

Expand to see code (spoiler alert)
defmodule RPG do
  defmodule Character do
    defstruct health: 100, mana: 0
  end

  defmodule LoafOfBread do
    defstruct []
  end

  defmodule ManaPotion do
    defstruct strength: 10
  end

  defmodule Poison do
    defstruct []
  end

  defmodule EmptyBottle do
    defstruct []
  end

  defprotocol Edible do
    @spec eat(t(), %RPG.Character{}) :: any()
    def eat(item, character)
  end

  defimpl Edible, for: LoafOfBread do
    @spec eat(%RPG.LoafOfBread{}, %RPG.Character{}) :: {nil, %RPG.Character{}}
    def eat(_item, character), do: {nil, %Character{character | health: character.health + 5}}
  end

  defimpl Edible, for: ManaPotion do
    @spec eat(%RPG.ManaPotion{}, %RPG.Character{}) :: {%RPG.EmptyBottle{}, %RPG.Character{}}
    def eat(item, character),
      do: {%RPG.EmptyBottle{}, %Character{character | mana: character.mana + item.strength}}
  end

  defimpl Edible, for: Poison do
    @spec eat(%RPG.Poison{}, %RPG.Character{}) :: {%RPG.EmptyBottle{}, %RPG.Character{}}
    def eat(_item, character), do: {%RPG.EmptyBottle{}, %Character{character | health: 0}}
  end
end

Notes

Overall progress

|

🗓️
View gist on GitHub
Exercise on Exercism
View my solution
View gist on GitHub
Exercise on Exercism
View my solution
View gist on GitHub
Exercise on Exercism
View my solution
Boutique Suggestions
Community Garden
Bread And Potions
Progress
An image showing my progress on Exercism. It's 19.9% as of Wednesday, 24 August 2022.