-module(gleam@queue). -compile(no_auto_import). -export([new/0, from_list/1, to_list/1, is_empty/1, length/1, push_back/2, push_front/2, pop_back/1, pop_front/1, reverse/1, is_logically_equal/3, is_equal/2]). new() -> {queue, [], []}. from_list(List) -> {queue, List, []}. to_list(Queue) -> gleam@list:append( erlang:element(3, Queue), gleam@list:reverse(erlang:element(2, Queue)) ). is_empty(Queue) -> (erlang:element(2, Queue) =:= []) andalso (erlang:element(3, Queue) =:= []). length(Queue) -> gleam@list:length( erlang:element(2, Queue) ) + gleam@list:length(erlang:element(3, Queue)). push_back(Queue, Item) -> {queue, [Item | erlang:element(2, Queue)], erlang:element(3, Queue)}. push_front(Queue, Item) -> {queue, erlang:element(2, Queue), [Item | erlang:element(3, Queue)]}. pop_back(Queue) -> case Queue of {queue, [], []} -> {error, nil}; {queue, In, []} -> pop_back({queue, [], gleam@list:reverse(In)}); {queue, In1, [First | Rest]} -> Queue1 = {queue, In1, Rest}, {ok, {First, Queue1}} end. pop_front(Queue) -> case Queue of {queue, [], []} -> {error, nil}; {queue, [], Out} -> pop_front({queue, gleam@list:reverse(Out), []}); {queue, [First | Rest], Out1} -> Queue1 = {queue, Rest, Out1}, {ok, {First, Queue1}} end. reverse(Queue) -> {queue, erlang:element(3, Queue), erlang:element(2, Queue)}. check_equal(Xs, XTail, Ys, YTail, Eq) -> case {Xs, XTail, Ys, YTail} of {[], [], [], []} -> true; {[X | Xs1], _, [Y | Ys1], _} -> case Eq(X, Y) of false -> false; true -> check_equal(Xs1, XTail, Ys1, YTail, Eq) end; {[], [_ | _], _, _} -> check_equal(gleam@list:reverse(XTail), [], Ys, YTail, Eq); {_, _, [], [_ | _]} -> check_equal(Xs, XTail, gleam@list:reverse(YTail), [], Eq); {_, _, _, _} -> false end. is_logically_equal(A, B, ElementIsEqual) -> check_equal( erlang:element(3, A), erlang:element(2, A), erlang:element(3, B), erlang:element(2, B), ElementIsEqual ). is_equal(A, B) -> check_equal( erlang:element(3, A), erlang:element(2, A), erlang:element(3, B), erlang:element(2, B), fun(A1, B1) -> A1 =:= B1 end ).