-module(counter). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([new/0, insert/2, get/2, total/1, keys/1, values/1, elements/1, update/2, add/2, subtract/2, size/1, to_list/1, most_common/2, from_list/1, to_dict/1, from_dict/1]). -export_type([counter/1]). -opaque counter(OHQ) :: {counter, gleam@dict:dict(OHQ, integer())}. -spec new() -> counter(any()). new() -> {counter, gleam@dict:new()}. -spec insert(counter(OHT), OHT) -> counter(OHT). insert(Counter, Item) -> _pipe = erlang:element(2, Counter), _pipe@2 = gleam@dict:update( _pipe, Item, fun(Count) -> begin _pipe@1 = Count, gleam@option:unwrap(_pipe@1, 0) end + 1 end ), {counter, _pipe@2}. -spec get(counter(OHW), OHW) -> integer(). get(Counter, Item) -> _pipe = erlang:element(2, Counter), _pipe@1 = gleam@dict:get(_pipe, Item), gleam@result:unwrap(_pipe@1, 0). -spec total(counter(any())) -> integer(). total(Counter) -> _pipe = erlang:element(2, Counter), _pipe@1 = maps:to_list(_pipe), _pipe@2 = gleam@list:map(_pipe@1, fun gleam@pair:second/1), gleam@int:sum(_pipe@2). -spec keys(counter(OIE)) -> list(OIE). keys(Counter) -> _pipe = erlang:element(2, Counter), gleam@dict:keys(_pipe). -spec values(counter(any())) -> list(integer()). values(Counter) -> _pipe = erlang:element(2, Counter), gleam@dict:values(_pipe). -spec prepend_repeated_item(OIN, integer(), list(OIN)) -> list(OIN). prepend_repeated_item(Item, Times, Acc) -> gleam@bool:guard( Times =< 0, Acc, fun() -> prepend_repeated_item(Item, Times - 1, [Item | Acc]) end ). -spec elements(counter(OIK)) -> list(OIK). elements(Counter) -> _pipe = erlang:element(2, Counter), _pipe@1 = maps:to_list(_pipe), gleam@list:fold( _pipe@1, [], fun(Items, Item) -> prepend_repeated_item( erlang:element(1, Item), erlang:element(2, Item), Items ) end ). -spec update(counter(OIQ), list(OIQ)) -> counter(OIQ). update(Counter, Items) -> _pipe = Items, gleam@list:fold(_pipe, Counter, fun(Counter@1, Item) -> _pipe@1 = Counter@1, insert(_pipe@1, Item) end). -spec add(counter(OIU), counter(OIU)) -> counter(OIU). add(Counter_1, Counter_2) -> _pipe = gleam@dict:combine( erlang:element(2, Counter_1), erlang:element(2, Counter_2), fun gleam@int:add/2 ), {counter, _pipe}. -spec subtract(counter(OIY), counter(OIY)) -> counter(OIY). subtract(Counter_1, Counter_2) -> Dict_1 = erlang:element(2, Counter_1), Dict_2 = erlang:element(2, Counter_2), Diff = gleam@dict:drop(Dict_2, gleam@dict:keys(Dict_1)), Diff_2 = gleam@dict:drop(Dict_2, gleam@dict:keys(Diff)), _pipe = gleam@dict:combine(Dict_1, Diff_2, fun gleam@int:subtract/2), _pipe@1 = gleam@dict:filter(_pipe, fun(_, B) -> B > 0 end), {counter, _pipe@1}. -spec size(counter(any())) -> integer(). size(Counter) -> _pipe = erlang:element(2, Counter), maps:size(_pipe). -spec to_list(counter(OJE)) -> list({OJE, integer()}). to_list(Counter) -> _pipe = erlang:element(2, Counter), maps:to_list(_pipe). -spec most_common(counter(OIA), gleam@option:option(integer())) -> list({OIA, integer()}). most_common(Counter, N) -> Counter@1 = begin _pipe = Counter, _pipe@1 = to_list(_pipe), gleam@list:sort( _pipe@1, fun(A, B) -> gleam@int:compare(erlang:element(2, B), erlang:element(2, A)) end ) end, case N of {some, N@1} -> _pipe@2 = Counter@1, gleam@list:take(_pipe@2, N@1); none -> Counter@1 end. -spec from_list(list(OJH)) -> counter(OJH). from_list(Items) -> update(new(), Items). -spec to_dict(counter(OJK)) -> gleam@dict:dict(OJK, integer()). to_dict(Counter) -> erlang:element(2, Counter). -spec from_dict(gleam@dict:dict(OJO, integer())) -> counter(OJO). from_dict(D) -> _pipe = D, {counter, _pipe}.