Simple solution for State Machine Exercise 6.11

35 views
Skip to first unread message

shay shimony

unread,
Sep 24, 2018, 2:55:43 PM9/24/18
to scala-functional
Hello,
I would like to propose different solution than the one provided, for this exercise.
I use the "update" code in the original solution, but in simpler way.

def simulateMachine(inputs: List[Input]): State[Machine, (Int, Int)] = {
    val z: State[Machine, (Int, Int)] = State(m => ((m.coins, m.candies), m))
    inputs.foldRight(z)((input, acc) => State(m => acc.run(update(input)(m))))
}

val update: Input => Machine => Machine =
  (i: Input) => (s: Machine) =>
    (i, s) match {
      case (_, Machine(_, 0, _)) => s
      case (Coin, Machine(false, _, _)) => s
      case (Turn, Machine(true, _, _)) => s
      case (Coin, Machine(true, candy, coin)) =>
        Machine(false, candy, coin + 1)
      case (Turn, Machine(false, candy, coin)) =>
        Machine(true, candy - 1, coin)
    }

Below I added trace for execution of simulateMachine(List(Coin, Turn)). Copying to text editor can help you follow with all the parenthesis.
First, the foldRight execution can be described like:
f(C, f(T, z))
f(C, f(T, State(m0 => ((m0.coins, m0.candies), m0))))
f(C, State(m1 => State(m0 => ((m0.co, m0.ca), m0)).run(update(T)(m1))))
State(m2 => State(m1 => State(m0 => ((m0.co, m0.ca), m0)).run(update(T)(m1))).run(update(C)(m2)))

Now call run over it:
State(m2 => State(m1 => State(m0 => ((m0.co, m0.ca), m0)).run(update(T)(m1))).run(update(C)(m2))).run(Machine(true, 10, 0))
State(m1 => State(m0 => ((m0.co, m0.ca), m0)).run(update(T)(m1))).run(update(C)(Machine(true, 10, 0)))
State(m1 => State(m0 => ((m0.co, m0.ca), m0)).run(update(T)(m1))).run(Machine(false, 10, 1))
State(m0 => ((m0.co, m0.ca), m0)).run(update(T)(Machine(false, 10, 1)))
State(m0 => ((m0.co, m0.ca), m0)).run(Machine(true, 9, 1))
((Machine(true, 9, 1).co, Machine(true, 9, 1).ca), Machine(true, 9, 1))
((1, 9), Machine(true, 9, 1))

Shay
Reply all
Reply to author
Forward
0 new messages