Skip to content

Instantly share code, notes, and snippets.

@Lysxia
Created September 26, 2017 00:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lysxia/54fcfe0c34efd63657d9a76213566e01 to your computer and use it in GitHub Desktop.
Save Lysxia/54fcfe0c34efd63657d9a76213566e01 to your computer and use it in GitHub Desktop.
-module(sm).
-export([multi_step/1,
multi_steps/1
]).
-type instr() :: {push, integer()} | {pop, pos_integer()}.
-type state() :: {non_neg_integer(), [instr()], [integer()]}.
-spec step(state()) -> state() | halt | err.
step({PC, Is, S}) ->
case nth(PC, Is) of
none -> err;
{push, X} -> {Is, [X|S]};
{pop, N} ->
case rotate(N, S) of
err -> err;
S1 -> {Is, S1}
end
end;
step({[], _}) -> halt.
nth(0, [X|_]) -> X;
nth(N, [_|Xs]) -> nth(N-1, Xs);
nth(_, []) -> none.
-spec rotate(pos_integer(), list()) -> list() | err.
rotate(N, Xs) -> rotate_(N, [], Xs).
rotate_(0, Ys, [_|Xs]) -> Ys ++ Xs;
rotate_(N, Ys, [X|Xs]) -> rotate_(N-1, [X|Ys], Xs);
rotate_(_, _, _) -> err.
-spec multi_step(state()) -> [integer()] | err.
multi_step(St = {_, _, S}) ->
case step(St) of
err -> err;
halt -> S;
St2 -> multi_step(St2)
end.
-spec multi_steps(state()) -> ok.
multi_steps(St) ->
case multi_step(St) of
err -> ok;
_ -> throw(ok)
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment