LoginSignup
19
18

More than 5 years have passed since last update.

進捗どうですかと煽ってくるプログラムをElixirのAgentとStream.transform/2を使って状態遷移で解く

Last updated at Posted at 2015-08-19

Agent を使って状態遷移を管理して解いてみた.

defmodule Shinchoku do
  def start_link do
    {:ok, pid} = Agent.start_link(fn -> "" end)
    pid
  end

  # うまくいっている途中なら :progress
  # 失敗してやりなおしなら :reset
  # 終わったなら :done
  # を返す
  def get(pid, given) do
    Agent.get_and_update(pid,
      fn now ->
        case {now, given} do
          {"",     "進捗"} -> {:progress, "進捗"}
          {"進捗", "どう"} -> {:progress, "どう"}
          {"どう", "です"} -> {:progress, "です"}
          {"です", "か"}   -> {:done,     "か"}
          _                -> {:reset,    ""}
        end
      end)
  end

  def stream do
    Stream.repeatedly(fn ->
      Enum.shuffle(["進捗", "どう", "です", "か"]) |> hd
    end)
    |> Stream.transform({start_link, 0, :reset}, fn(str, {pid, n, state}) ->
      if state === :done do
        {:halt, {pid, n, state}}
      else
        amount = n + String.length(str)
        state = get(pid, str)
        {[{str, amount, state}], {pid, amount, state}}
      end
    end)
  end
end

:random.seed(:os.timestamp)

Shinchoku.stream
|> Stream.each(fn {str, _amount, _state} -> IO.write(str) end)
|> Stream.each(fn {_str, amount, state} ->
  if state === :done, do: IO.write("???\n#{amount}文字で煽られました.!!!!!\n")
end)
|> Stream.run

#> 進捗どうどう進捗ですですかどうですですかかかかどうか進捗かどう進捗ですか進捗進捗かどうですです進捗ですかですですどうかかかどうどうですどう進捗どうですどう進捗ですかですですかどう進捗ですですどうかですどうですかかどうかどうかどう進捗どうかどうかですです進捗進捗です進捗進捗どうどうです進捗です進捗か進捗どうどうどう進捗かどうですどうどうかどうですどうかかどうです進捗どうどう進捗進捗かかですですどう進捗かかかです進捗か進捗進捗ですどうですどうどうどうですかですですかどうどうどうです進捗どうですか???
#> 248文字で煽られました.!!!!!

Stream.transform/2 の第二引数に渡す関数の返り値が {:halt, acc} だと Stream は終わるので,明示的に終了を試みなくても勝手に終わる.

Stream の内容は以下のデバッグのように
{文字, これまでの文字数, 状態}
な 3 要素のタプルになっている.
状態が :done になったら終わりを意味する.

Shinchoku.stream
|> Stream.each(&IO.inspect/1)
|> Enum.take(10)

#> {"どう", 2, :reset}
#> {"どう", 4, :reset}
#> {"進捗", 6, :progress}
#> {"どう", 8, :progress}
#> {"か", 9, :reset}
#> {"進捗", 11, :progress}
#> {"か", 12, :reset}
#> {"です", 14, :reset}
#> {"か", 15, :reset}
#> {"どう", 17, :reset}
19
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
18