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

Rock Paper Scissors

rock_paper_scissors.livemd

Rock Paper Scissors

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

Setup

Ensure you type the ea keyboard shortcut to evaluate all Elixir cells before starting. Alternatively you can evaluate the Elixir cells as you read.

Create the Perfect AI

In the Elixir cell below, you’re going to create the perfect AI for rock paper scissors.

flowchart LR
scissors --beats--> paper --beats--> rock --beats--> scissors

You are only allowed to use boolean operators &&, ==, and || and the match operator =.

Remember that you can conditionally return a value with:

player_choice = :rock

ai_choice = player_choice == :rock && :paper

Given a player_choice of either :rock, :paper, or :scissors determining the winning ai_choice.

Replace nil with your answer. Change player_choice to :rock, :paper, and :scissors to ensure your solution works correctly.

ExUnit.start(auto_run: false)

defmodule Assertion do
  use ExUnit.Case

  test "Exercise" do
    try do
      Process.flag(:trap_exit, true)
      player_choice = :rock

      ai_choice =
        (player_choice == :scissors && :rock) ||
          (player_choice == :rock && :paper) ||
          (player_choice == :paper && :scissors)

      case player_choice do
        :rock ->
          assert ai_choice === :paper,
                 "when player_choice is :rock, ai_choice should be :paper."

        :paper ->
          assert ai_choice === :scissors,
                 "when player_choice is :paper, ai_choice should be :scissors."

        :scissors ->
          assert ai_choice === :rock,
                 "when player_choice is :scissors, ai_choice should be :rock."
      end
    catch
      error ->
        flunk("""
          Your solution threw the following error:

          #{inspect(error)}
        """)

      :exit, {error, {GenServer, message_type, [_pid, message, _timeout]}} ->
        flunk("""
            GenServer crashed with the following error:

            #{inspect(error)}

            When it recieved: #{inspect(message)} #{message_type}

            Likely you need to define the corresponding handler for #{inspect(message)}.

            Ensure you defined a `handle_call/3`, `handle_info/2`, or `handle_cast/2` or appropriate handler function.

              def handle_call(:message, _from, state) do
                ...
              end

            Then ensure you call `GenServer.call/2`, `GenServer.cast/2`, or otherwise send the message correctly.

              GenServer.call(pid, :message)
        """)

      :exit, error ->
        flunk("""
          Unhandled exit with the following error:

          #{inspect(error)}
        """)
    after
      # all warnings and errors are printed to the previous Kino Frame
      # to avoid cluttering the test results display.
      Process.sleep(10)
      Kino.render(Kino.Markdown.new("### Test Results 

"
)) end end end ExUnit.run() # Make variables and modules defined in the test available. # Also allows for exploration using the output of the cell. # Unfortunately, this results in duplication of warnings. player_choice = :rock ai_choice = (player_choice == :scissors && :rock) || (player_choice == :rock && :paper) || (player_choice == :paper && :scissors)

Create Two Player Rock Paper Scissors

In the Elixir cell below, you’re going to create a two player game of rock paper scissors.

As earlier, you should only use the &&, =, ===, and || operators.

Given player1_choice and player2_choice are either :rock, :paper, or :scissors. Determine the winner as either :player1 or :player2.

flowchart LR
p1c[player_1_choice]
p2c[player_2_choice]
w[winner]
p1[:player1]
p2[:player2]

p1c --> w
p2c --> w
w --> p1
w --> p2

Replace nil with your answer.

ExUnit.start(auto_run: false)

defmodule Assertion do
  use ExUnit.Case

  test "Exercise" do
    try do
      Process.flag(:trap_exit, true)
      # Will be either :rock, :paper, or :scissors
      player1_choice = Utils.random(:rock_paper_scissors)
      # Will be either :rock, :paper, or :scissors
      player2_choice = Utils.random(:rock_paper_scissors)

      winner =
        (player1_choice == :scissors && player2_choice == :rock && :player2) ||
          (player1_choice == :rock && player2_choice == :paper && :player2) ||
          (player1_choice == :paper && player2_choice == :scissors && :player2) ||
          (player1_choice == player2_choice && :draw) ||
          :player1

      case {player1_choice, player2_choice} do
        {:rock, :scissors} -> assert winner == :player1
        {:paper, :rock} -> assert winner == :player1
        {:scissors, :paper} -> assert winner == :player1
        {:scissors, :rock} -> assert winner == :player2
        {:rock, :paper} -> assert winner == :player2
        {:paper, :scissors} -> assert winner == :player2
        _ -> assert winner == :draw
      end
    catch
      error ->
        flunk("""
          Your solution threw the following error:

          #{inspect(error)}
        """)

      :exit, {error, {GenServer, message_type, [_pid, message, _timeout]}} ->
        flunk("""
            GenServer crashed with the following error:

            #{inspect(error)}

            When it recieved: #{inspect(message)} #{message_type}

            Likely you need to define the corresponding handler for #{inspect(message)}.

            Ensure you defined a `handle_call/3`, `handle_info/2`, or `handle_cast/2` or appropriate handler function.

              def handle_call(:message, _from, state) do
                ...
              end

            Then ensure you call `GenServer.call/2`, `GenServer.cast/2`, or otherwise send the message correctly.

              GenServer.call(pid, :message)
        """)

      :exit, error ->
        flunk("""
          Unhandled exit with the following error:

          #{inspect(error)}
        """)
    after
      # all warnings and errors are printed to the previous Kino Frame
      # to avoid cluttering the test results display.
      Process.sleep(10)
      Kino.render(Kino.Markdown.new("### Test Results 

"
)) end end end ExUnit.run() # Make variables and modules defined in the test available. # Also allows for exploration using the output of the cell. # Unfortunately, this results in duplication of warnings. # Will be either :rock, :paper, or :scissors player1_choice = Utils.random(:rock_paper_scissors) # Will be either :rock, :paper, or :scissors player2_choice = Utils.random(:rock_paper_scissors) winner = (player1_choice == :scissors && player2_choice == :rock && :player2) || (player1_choice == :rock && player2_choice == :paper && :player2) || (player1_choice == :paper && player2_choice == :scissors && :player2) || (player1_choice == player2_choice && :draw) || :player1

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 rock paper scissors exercise"