Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Bottles of Soda

bottles_of_soda.livemd

Bottles of Soda

Mix.install([
  {:kino, github: "livebook-dev/kino", override: true},
  {:kino_lab, "~> 0.1.0-dev", github: "jonatanklosko/kino_lab"},
  {:vega_lite, "~> 0.1.4"},
  {:kino_vega_lite, "~> 0.1.1"},
  {:benchee, "~> 0.1"},
  {:ecto, "~> 3.7"},
  {:math, "~> 0.7.0"},
  {:faker, "~> 0.17.0"},
  {:utils, path: "#{__DIR__}/../utils"},
  {:tested_cell, git: "https://github.com/BrooklinJazz/tested_cell"}
])

Navigation

Return Home Report An Issue

Bottles of Soda

In the Elixir cell below create a module BottlesOfSoda with a function on_the_wall/0.

It should return a list with the following lyrics from 99 to 0. Ensure you handle the special cases for 2, 1 and 0.

BottlesOfSoda.on_the_wall()
[
"99 bottles of soda on the wall.
99 bottles of soda.
Take one down, pass it around.
98 bottles of soda on the wall.",

# ... and so on until you reach 2 where the grammar changes
"2 bottles of soda on the wall.
2 bottles of soda.
Take one down, pass it around.
1 bottle of soda on the wall.",

"1 bottle of soda on the wall.
1 bottle of soda.
Take one down, pass it around.
0 bottles of soda on the wall.",

"No more bottles of soda on the wall, no more bottles of soda.
Go to the store and buy some more, 99 bottles of soda on the wall."
]
ExUnit.start(auto_run: false)

defmodule Assertion do
  use ExUnit.Case

  test "" do
    defmodule BottlesOfSoda do
      def on_the_wall do
      end
    end

    defmodule Solutions.BottlesOfSoda do
      def on_the_wall do
        Enum.to_list(99..0)
        |> Enum.map(&sentence/1)
      end

      defp container(1), do: "bottle"
      defp container(_n), do: "bottles"

      defp sentence(0) do
        "No more bottles of soda on the wall, no more bottles of soda.\nGo to the store and buy some more, 99 bottles of soda on the wall."
      end

      defp sentence(n) when n > 0 do
        "#{n} #{container(n)} of soda on the wall.\n#{n} #{container(n)} of soda.\nTake one down, pass it around.\n#{n - 1} #{container(n - 1)} of soda on the wall."
      end
    end

    result = BottlesOfSoda.on_the_wall()
    assert result, "Implement the `on_the_wall/0` function."
    assert is_list(result), "`on_the_wall/0` should return a list."

    assert Enum.at(result, 0) ==
             "99 bottles of soda on the wall.\n99 bottles of soda.\nTake one down, pass it around.\n98 bottles of soda on the wall."

    assert length(result) == 100, "There should be 100 total verses."

    assert Enum.at(result, 97) ==
             "2 bottles of soda on the wall.\n2 bottles of soda.\nTake one down, pass it around.\n1 bottle of soda on the wall."

    assert Enum.at(result, 98) ==
             "1 bottle of soda on the wall.\n1 bottle of soda.\nTake one down, pass it around.\n0 bottles of soda on the wall."

    assert Enum.at(result, 99) ==
             "No more bottles of soda on the wall, no more bottles of soda.\nGo to the store and buy some more, 99 bottles of soda on the wall."

    assert result == Utils.Solutions.BottlesOfSoda.on_the_wall()
  end
end

ExUnit.run()

# Make variables and modules defined in the test available.
# Also allows for exploration using the output of the cell.
defmodule BottlesOfSoda do
  def on_the_wall do
  end
end

(Bonus) Bottles of ???

Make a new BottlesOfBlank module below with the following modifications.

  • It should be able to accept a custom drink instead of "soda".
  • It should be able to accept a custom container instead of "bottles".
  • It should be able to accept a range of lyrics, and only return than range of lyrics.

For example,

BottlesOfBlank.on_the_wall(3..0, "pop", "cans")
[
"3 cans of pop on the wall.
3 cans of pop.
Take one down, pass it around.
2 cans of pop on the wall.",

"2 cans of pop on the wall.
2 cans of pop.
Take one down, pass it around.
1 can of pop on the wall.",

"1 can of pop on the wall.
1 can of pop.
Take one down, pass it around.
0 cans of pop on the wall.",

"No more cans of pop on the wall, no more cans of pop.
Go to the store and buy some more, 99 cans of pop on the wall.
"
]

You can assume any container will be provided in it’s plural form so a "can" will always be passed into the function as "cans". You only need to worry about containers whose plural form ends in an s.

ExUnit.start(auto_run: false)

defmodule Assertion do
  use ExUnit.Case

  test "" do
    defmodule BottlesOfBlank do
      def on_the_wall(range, beverage, container) do
      end
    end

    result = BottlesOfBlank.on_the_wall(50..0, "pop", "cans")

    assert result, "Implement the `on_the_wall/3` function."

    assert is_list(result), "`on_the_wall/3` should return a list."

    assert Enum.at(result, 0) ==
             "50 cans of pop on the wall.\n50 cans of pop.\nTake one down, pass it around.\n49 cans of pop on the wall."

    assert length(result) == 51, "There should be 51 total verses."

    assert Enum.at(result, 48) ==
             "2 cans of pop on the wall.\n2 cans of pop.\nTake one down, pass it around.\n1 can of pop on the wall."

    assert Enum.at(result, 49) ==
             "1 can of pop on the wall.\n1 can of pop.\nTake one down, pass it around.\n0 cans of pop on the wall."

    assert Enum.at(result, 50) ==
             "No more cans of pop on the wall, no more cans of pop.\nGo to the store and buy some more, 99 cans of pop on the wall."
  end
end

ExUnit.run()

# Make variables and modules defined in the test available.
# Also allows for exploration using the output of the cell.
defmodule BottlesOfBlank do
  def on_the_wall(range, beverage, container) do
  end
end

Commit Your Progress

Run the following in your command line from the project folder to track and save your progress in a Git commit.

$ git add .
$ git commit -m "finish bottles of soda exercise"