概要
paiza.ioでelixirやってみた。
練習問題やってみた。
練習問題
俺cpuのアセンブラをコンパイルしてelixirのソースコードを生成せよ。
fizzbuzzを解け。
サンプルコード
defmodule Stack do
use Agent
def start_link do
Agent.start_link(fn ->
[]
end, name: __MODULE__)
end
def pop do
v = Agent.get(__MODULE__, fn stack ->
stack
|> List.last()
end)
Agent.update(__MODULE__, fn stack ->
po = length(stack) - 1
List.delete_at(stack, po)
end)
v
end
def push(v) do
Agent.update(__MODULE__, fn stack ->
stack ++ [v]
end)
end
end
defmodule Va do
use Agent
def start_link() do
Agent.start_link(fn ->
0
end, name: __MODULE__)
end
def get() do
Agent.get(__MODULE__, fn v ->
v
end)
end
def set(x) do
Agent.update(__MODULE__, fn v ->
x
end)
end
end
defmodule Main do
def loop0() do
IO.puts("""
loop(1)
end
def loop(v) do
if v == 0 do
else
""")
end
def add() do
v0 = Stack.pop()
v1 = Stack.pop()
Stack.push("#{v1} + #{v0}")
end
def rem() do
v0 = Stack.pop()
v1 = Stack.pop()
Stack.push("rem(#{v1}, #{v0})")
end
def eq() do
Stack.push("==")
end
def skip() do
IO.puts(" loop(1)")
IO.puts(" end")
end
def gt() do
Stack.push(">")
end
def out() do
IO.puts(" IO.puts(#{Stack.pop()})")
end
def push(s) do
Stack.push(s)
end
def if_(s) do
v0 = Stack.pop()
v1 = Stack.pop()
v2 = Stack.pop()
IO.puts("""
if #{v1} #{v0} #{v2} do
loop(0)
else
""")
end
def nf(s) do
v0 = Stack.pop()
v1 = Stack.pop()
v2 = Stack.pop()
IO.puts(" if #{v2} #{v0} #{v1} do")
end
def jmp(s) do
end
def set(s) do
IO.puts(" #{s} = #{Stack.pop()}")
IO.puts(" Va.set(#{s})")
Stack.push(s)
end
def get(s) do
IO.puts(" #{s} = Va.get()")
Stack.push(s)
end
def asm(str) do
Enum.map(String.split(str, "\n"), fn st ->
s = String.split(st, " ")
cond do
Enum.at(s, 0) == "loop" ->
loop0()
Enum.at(s, 0) == "skip0" ->
skip()
Enum.at(s, 0) == "skip1" ->
skip()
Enum.at(s, 0) == "skip2" ->
skip()
Enum.at(s, 1) == "+" ->
add()
Enum.at(s, 1) == "%" ->
rem()
Enum.at(s, 1) == "=" ->
eq()
Enum.at(s, 1) == "out" ->
out()
Enum.at(s, 1) == ">" ->
gt()
Enum.at(s, 1) == "jmp" ->
jmp(Enum.at(s, 2))
Enum.at(s, 1) == "if" ->
if_(Enum.at(s, 2))
Enum.at(s, 1) == "nf" ->
nf(Enum.at(s, 2))
Enum.at(s, 1) == "set" ->
set(Enum.at(s, 2))
Enum.at(s, 1) == "get" ->
get(Enum.at(s, 2))
true ->
push(Enum.at(s, 1))
end
end)
end
def start(str) do
IO.puts("""
defmodule Va do
use Agent
def start_link() do
Agent.start_link(fn ->
0
end, name: __MODULE__)
end
def get() do
Agent.get(__MODULE__, fn v ->
v
end)
end
def set(x) do
Agent.update(__MODULE__, fn v ->
x
end)
end
end
Va.start_link
defmodule Main do
def main do
""")
asm(str)
IO.puts("""
loop(1)
end
end
end
end
Main.main()
""")
end
end
Va.start_link
Stack.start_link
"""
0
set a
loop
get a
1
+
set a
get a
15
%
0
=
nf skip0
"FizzBuzz"
out
skip0
get a
5
%
0
=
nf skip1
"Buzz"
out
skip1
get a
3
%
0
=
nf skip2
"Fizz"
out
skip2
100
get a
>
if end
get a
out
jmp loop
"""
|> Main.start()
実行結果
defmodule Va do
use Agent
def start_link() do
Agent.start_link(fn ->
0
end, name: __MODULE__)
end
def get() do
Agent.get(__MODULE__, fn v ->
v
end)
end
def set(x) do
Agent.update(__MODULE__, fn v ->
x
end)
end
end
Va.start_link
defmodule Main do
def main do
a = 0
Va.set(a)
loop(1)
end
def loop(v) do
if v == 0 do
else
a = Va.get()
a = a + 1
Va.set(a)
a = Va.get()
if rem(a, 15) == 0 do
IO.puts("FizzBuzz")
loop(1)
end
a = Va.get()
if rem(a, 5) == 0 do
IO.puts("Buzz")
loop(1)
end
a = Va.get()
if rem(a, 3) == 0 do
IO.puts("Fizz")
loop(1)
end
a = Va.get()
if a > 100 do
loop(0)
else
a = Va.get()
IO.puts(a)
loop(1)
end
end
end
end
Main.main()
生成したコードを実行
成果物
以上。