stackcats
How to use GenServer in leetcode?
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?
Most Liked
mudasobwa
This line in subsequent calls to init_/1 won’t do what you think it will. There might be only one instance with the name RLEIterator running, meaning the second and all other calls would return {:error, {:already_started, pid}} tuple and next/1 will send a message to the very first instance started. That is one of the reasons you are better to directly pattern match on the return value of GenServer.start_link/3.
{:ok, _pid} = GenServer.start_link(__MODULE__, []} # , name: __MODULE__)
You likely need an agent, keeping the map %{encoding ⇒ pid} and a bunch of anonymous instances of RLEIterators.







