The problem needs to keep track of the encoding list
So I used GenServer to solve this
This is the first version of the code
defmodule RLEIterator do
use GenServer
@spec init_(encoding :: [integer]) :: any
def init_(encoding) do
GenServer.start_link(__MODULE__, encoding, name: __MODULE__)
end
@spec next(n :: integer) :: integer
def next(n) do
GenServer.call(__MODULE__, {:next, n})
end
def init(encoding) do
{:ok, encoding}
end
def handle_call({:next, n}, _from, state) do
{res, new_state} = next_(n, state)
{:reply, res, new_state}
end
defp next_(_n, []), do: {-1, []}
defp next_(n, [ct, num | rest]) do
if ct >= n do
{num, [ct - n, num | rest]}
else
next_(n - ct, rest)
end
end
end
The code will be called as such:
RLEIterator.init_([3, 8, 2, 5])
param_1 = RLEIterator.next(2)
RLEIterator.init_([2, 5, 3, 8])
param_1 = RLEIterator.next(5)
I got the wrong answer.
Because there are multiple test cases with one GenServer instance.
So I changed my code
defmodule RLEIterator do
use GenServer
@spec init_(encoding :: [integer]) :: any
def init_(encoding) do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
GenServer.call(__MODULE__, {:init, encoding})
end
@spec next(n :: integer) :: integer
def next(n) do
GenServer.call(__MODULE__, {:next, n})
end
def init(encoding) do
{:ok, encoding}
end
def handle_call({:init, encoding}, _from, _state) do
{:reply, [], encoding}
end
def handle_call({:next, n}, _from, state) do
{res, new_state} = next_(n, state)
{:reply, res, new_state}
end
defp next_(_n, []), do: {-1, []}
defp next_(n, [ct, num | rest]) do
if ct >= n do
{num, [ct - n, num | rest]}
else
next_(n - ct, rest)
end
end
end
I think it’s so ugly in function init_
.
How to improve the code?