Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

max heap stack subtree implementation

  • Loading branch information...
commit 35c0e3c104b6a88820d6f992359e5f3ece2a6fdc 1 parent d2520d3
@etrepum authored
Showing with 121 additions and 0 deletions.
  1. +64 −0 src/cstack.erl
  2. +57 −0 src/markov_cstack.erl
View
64 src/cstack.erl
@@ -0,0 +1,64 @@
+%% @doc Counting stack. Biggest items at the front.
+%% O(N) worst case for every operation.
+-module(cstack).
+
+-type(cstack(T) :: {Total :: non_neg_integer(),
+ [{T, Count :: non_neg_integer()}]}).
+
+-export([new/0, increment/2, increment/3, total/1,
+ from_list/1, to_list/1, seek/2]).
+
+-spec new() -> cstack(_).
+new() ->
+ {0, []}.
+
+-spec increment({T, non_neg_integer()}, cstack(T)) -> cstack(T).
+increment({K, Inc}, Stack) ->
+ increment(K, Inc, Stack).
+
+-spec increment(T, non_neg_integer(), cstack(T)) -> cstack(T).
+increment(K, Inc, {Total, L}) ->
+ {Inc + Total, inc(K, Inc, L)}.
+
+-spec to_list(cstack(T)) -> [{T, non_neg_integer()}].
+to_list({_Total, L}) ->
+ L.
+
+-spec from_list([{T, non_neg_integer()}]) -> cstack(T).
+from_list(L) ->
+ %% Sum and reverse the value sorted list.
+ lists:foldl(
+ fun (P={_K, V}, {T, Acc}) -> {V + T, [P | Acc]} end,
+ new(),
+ lists:keysort(2, L)).
+
+-spec total(cstack(_)) -> non_neg_integer().
+total({Total, _L}) ->
+ Total.
+
+-spec seek(non_neg_integer(), cstack(T)) -> T.
+seek(N, {Total, L}) when N < Total ->
+ seek2(N, L).
+
+seek2(N, [{K, V} | Rest]) ->
+ case N - V of
+ N1 when N1 >= 0 ->
+ seek2(N1, Rest);
+ _ ->
+ K
+ end.
+
+inc(K, Inc, L) ->
+ case lists:keyfind(K, 1, L) of
+ {_, N} ->
+ insort(K, Inc + N, true, L);
+ false ->
+ insort(K, Inc, false, L)
+ end.
+
+insort(K, V, Remove, [P={_K, V1} | T]) when V < V1 ->
+ [P | insort(K, V, Remove, T)];
+insort(K, V, true, L) ->
+ [{K, V} | lists:keydelete(K, 1, L)];
+insort(K, V, false, L) ->
+ [{K, V} | L].
View
57 src/markov_cstack.erl
@@ -0,0 +1,57 @@
+-module(markov_cstack).
+-export([new/1, from_list/2, to_list/1, append/3, lookup/2,
+ choose_nth/2]).
+
+-define(SUB, cstack).
+-define(WORD_MAX, 100).
+
+new([]) ->
+ gb_trees:empty().
+
+from_list(L, EmptyT) ->
+ lists:foldl(fun ({K, V}, T) ->
+ gb_trees:insert(K, subtree_from_list(V), T)
+ end,
+ EmptyT,
+ L).
+
+to_list(T) ->
+ to_orddict_iter(gb_trees:next(gb_trees:iterator(T))).
+
+append(K, V, T) ->
+ case gb_trees:lookup(K, T) of
+ none ->
+ gb_trees:insert(K, increment(V, ?SUB:new()), T);
+ {value, SubT} ->
+ gb_trees:update(K, increment(V, SubT), T)
+ end.
+
+increment(K, SubT) ->
+ ?SUB:increment(K, 1, SubT).
+
+lookup(K, T) ->
+ case gb_trees:lookup(K, T) of
+ {value, SubT} ->
+ case ?SUB:total(SubT) of
+ Total when Total > 0 ->
+ {value, {Total, SubT}};
+ Total ->
+ error({total_is_zero, Total, K, SubT})
+ end;
+ none ->
+ none
+ end.
+
+choose_nth(N, SubT) ->
+ ?SUB:seek(N - 1, SubT).
+
+subtree_from_list(L) ->
+ ?SUB:from_list(L).
+
+to_orddict_iter(none) ->
+ [];
+to_orddict_iter({K, V, Iter}) ->
+ [{K, to_orddict_subtree(V)} | to_orddict_iter(gb_trees:next(Iter))].
+
+to_orddict_subtree(T) ->
+ ?SUB:to_list(T).
Please sign in to comment.
Something went wrong with that request. Please try again.