paiza.ioでelixir その45

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
Forthインタープリタを書け。
forthで数9を4個つかって1から15までの数を表す式を実行せよ。
Enumを使え。

# サンプルコード

```
defmodule Forth do
	def start_link do
		Agent.start_link(fn ->
			[]
		end, name: __MODULE__)
	end
	def add do
		Agent.update(__MODULE__, fn stack ->
		    po = Enum.count(stack) - 1
			top = Enum.at(stack, po)
			tmp = Enum.with_index(stack)
		    po = po - 1
            stack = Enum.map(tmp, fn {val, ind} ->
                cond do
	            ind == po ->
		            val + top
	            true ->
		            val
	            end
            end)
			stack = Enum.drop(stack, -1)
		end)
	end
	def sub do
		Agent.update(__MODULE__, fn stack ->
		    po =  Enum.count(stack) - 1
			top = Enum.at(stack, po)
		    tmp = Enum.with_index(stack)
		    po = po - 1
            stack = Enum.map(tmp, fn {val, ind} ->
                cond do
	            ind == po ->
		            val - top
	            true ->
		            val
	            end
            end)
			stack = Enum.drop(stack, -1)
		end)
	end
	def mul do
		Agent.update(__MODULE__, fn stack ->
		    po =  Enum.count(stack) - 1
			top = Enum.at(stack, po)
		    tmp = Enum.with_index(stack)
		    po = po - 1
            stack = Enum.map(tmp, fn {val, ind} ->
                cond do
	            ind == po ->
		            val * top
	            true ->
		            val
	            end
            end)
			stack = Enum.drop(stack, -1)
		end)
	end
	def div do
		Agent.update(__MODULE__, fn stack ->
		    po =  Enum.count(stack) - 1
			top = Enum.at(stack, po)
		    tmp = Enum.with_index(stack)
		    po = po - 1
            stack = Enum.map(tmp, fn {val, ind} ->
                cond do
	            ind == po ->
		            val / top
	            true ->
		            val
	            end
            end)
			stack = Enum.drop(stack, -1)
		end)
	end
	def dup do
		Agent.update(__MODULE__, fn stack ->
		    po =  Enum.count(stack) - 1
			top = Enum.at(stack, po)
			stack = Enum.concat(stack, [top])
		end)
	end
	def drop do
		Agent.update(__MODULE__, fn stack ->
			stack = Enum.drop(stack, -1)
		end)
	end
	def get do
		Agent.get(__MODULE__, fn stack ->
		    po =  Enum.count(stack) - 1
			Enum.at(stack, po)
		end)
	end
	def push(n) do
		Agent.update(__MODULE__, fn stack ->
		    {v, _} = Integer.parse(n)
			stack = Enum.concat(stack, [v])
		end)
	end
end

defmodule Main do
    def run(str) do
    Enum.map(String.split(str, " "), fn s ->
        cond do
	    s == "+" ->
		    Forth.add
	    s == "-" ->
		    Forth.sub
	    s == "*" ->
		    Forth.mul
	    s == "/" ->
		    Forth.div
	    s == "dup" ->
		    Forth.dup
	    s == "drop" ->
		    Forth.drop
	    s == "." ->
		    IO.inspect Forth.get
	    true ->
            Forth.push(s)
        end
    end)
    end
end

Forth.start_link

Main.run("9 9 - 9 9 / .")

Main.run("9 9 / 9 9 / + .")# 2  ok

Main.run("9 9 + 9 + 9 / .")# 3  ok

Main.run("9 9 9 + 9 / dup + .")# 4  ok

Main.run("9 9 9 + 9 / dup + - .")# 5  ok

Main.run("9 dup 9 + 9 + 9 / - .")# 6  ok

Main.run("9 9 9 + 9 / - .")# 7  ok

Main.run("9 9 9 drop 9 / - .")# 8  ok

Main.run("9 9 - 9 * 9 + .")# 9  ok

Main.run("9 9 / 9 dup 9 / + .")# 10  ok

Main.run("9 9 9 + 9 / + .")# 11  ok

Main.run("9 dup 9 9 + + 9 / + .")# 12  ok

Main.run("9 9 9 + 9 / dup + + .")# 13  ok

Main.run("9 dup 9 9 + 9 / dup + - + .")# 14  ok

Main.run("9 dup dup 9 + 9 + 9 / - + .")# 15  ok

```

# 実行結果

```
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9
10.0
11.0
12.0
13.0
14.0
15.0
```

# 成果物


https://paiza.io/projects/wetRmfrt1F0jGXuK_8KxJQ


以上。