diff options
Diffstat (limited to 'aoc2023/build/packages/pqueue/src/pqueue2.erl')
-rw-r--r-- | aoc2023/build/packages/pqueue/src/pqueue2.erl | 483 |
1 files changed, 0 insertions, 483 deletions
diff --git a/aoc2023/build/packages/pqueue/src/pqueue2.erl b/aoc2023/build/packages/pqueue/src/pqueue2.erl deleted file mode 100644 index bbdeaaf..0000000 --- a/aoc2023/build/packages/pqueue/src/pqueue2.erl +++ /dev/null @@ -1,483 +0,0 @@ -%-*-Mode:erlang;coding:utf-8;tab-width:4;c-basic-offset:4;indent-tabs-mode:()-*- -% ex: set ft=erlang fenc=utf-8 sts=4 ts=4 sw=4 et nomod: -%%% -%%%------------------------------------------------------------------------ -%%% @doc -%%% ==Skew Heap Priority Queue.== -%%% Ulf Wiger suggested pursuing a skew heap as an optimal Erlang priority -%%% queue implementation. Unfortunately, testing has shown this solution to -%%% be more than 2 times slower than pqueue. -%%% @end -%%% -%%% MIT License -%%% -%%% Copyright (c) 2011-2020 Michael Truog <mjtruog at protonmail dot com> -%%% -%%% Permission is hereby granted, free of charge, to any person obtaining a -%%% copy of this software and associated documentation files (the "Software"), -%%% to deal in the Software without restriction, including without limitation -%%% the rights to use, copy, modify, merge, publish, distribute, sublicense, -%%% and/or sell copies of the Software, and to permit persons to whom the -%%% Software is furnished to do so, subject to the following conditions: -%%% -%%% The above copyright notice and this permission notice shall be included in -%%% all copies or substantial portions of the Software. -%%% -%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -%%% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -%%% DEALINGS IN THE SOFTWARE. -%%% -%%% @author Michael Truog <mjtruog at protonmail dot com> -%%% @copyright 2011-2020 Michael Truog -%%% @version 2.0.1 {@date} {@time} -%%%------------------------------------------------------------------------ - --module(pqueue2). --author('mjtruog at protonmail dot com'). - -%% external interface --export([in/2, - in/3, - is_empty/1, - is_queue/1, - len/1, - new/0, - out/1, - out/2, - pout/1, - to_list/1, - test/0]). - -%%%------------------------------------------------------------------------ -%%% External interface functions -%%%------------------------------------------------------------------------ - --ifdef(ERLANG_OTP_VERSION_16). --type pqueue2() :: - empty | - {integer(), pqueue2(), pqueue2(), element, term()} | - {integer(), pqueue2(), pqueue2(), queue, queue()}. --else. --type pqueue2() :: - empty | - {integer(), pqueue2(), pqueue2(), element, term()} | - {integer(), pqueue2(), pqueue2(), queue, queue:queue()}. --endif. - -%%------------------------------------------------------------------------- -%% @doc -%% ===Append an item to the tail of the 0 priority queue.=== -%% @end -%%------------------------------------------------------------------------- - --spec in(term(), pqueue2()) -> pqueue2(). - -in(Value, H) -> - in(Value, 0, H). - -%%------------------------------------------------------------------------- -%% @doc -%% ===Append an item to the tail of a specific priority queue.=== -%% @end -%%------------------------------------------------------------------------- - --spec in(term(), integer(), pqueue2()) -> pqueue2(). - -in(Value, P, H) -> - merge({P, empty, empty, element, Value}, H). - -%%------------------------------------------------------------------------- -%% @doc -%% ===Check if the priority queue is empty.=== -%% @end -%%------------------------------------------------------------------------- - --spec is_empty(pqueue2()) -> 'true' | 'false'. - -is_empty(empty) -> - true; -is_empty({_, HL, HR, queue, Queue}) -> - is_empty(HL) andalso is_empty(HR) andalso queue:is_empty(Queue); -is_empty(_) -> - false. - -%%------------------------------------------------------------------------- -%% @doc -%% ===Check if the priority queue type is as expected.=== -%% @end -%%------------------------------------------------------------------------- - --spec is_queue(pqueue2()) -> 'true' | 'false'. - -is_queue(empty) -> - true; -is_queue({P, _, _, element, _}) - when is_integer(P) -> - true; -is_queue({P, _, _, queue, Queue}) - when is_integer(P) -> - queue:is_queue(Queue); -is_queue(_) -> - false. - -%%------------------------------------------------------------------------- -%% @doc -%% ===Determine the length of a priority queue.=== -%% @end -%%------------------------------------------------------------------------- - --spec len(pqueue2()) -> non_neg_integer(). - -len(H) -> - len(0, out(H)). -len(I, {empty, _}) -> - I; -len(I, {{value, _}, H}) -> - len(I + 1, out(H)). - -%%------------------------------------------------------------------------- -%% @doc -%% ===Create a new priority queue.=== -%% @end -%%------------------------------------------------------------------------- - --spec new() -> pqueue2(). - -new() -> - empty. - -%%------------------------------------------------------------------------- -%% @doc -%% ===Take an item from the head of the priority queue.=== -%% @end -%%------------------------------------------------------------------------- - --spec out(pqueue2()) -> - {{'value', term()}, pqueue2()} | {'empty', pqueue2()}. - -out(empty) -> - {empty, empty}; -out({_, HL, HR, element, Value}) -> - {{value, Value}, merge(HL, HR)}; -out({P, HL, HR, queue, Queue}) -> - case queue:out(Queue) of - {{value, _} = Result, NewQueue} -> - {Result, {P, HL, HR, queue, NewQueue}}; - {empty, _} -> - out(merge(HL, HR)) - end. - -%%------------------------------------------------------------------------- -%% @doc -%% ===Take an item of a specific priority from the head of the queue.=== -%% @end -%%------------------------------------------------------------------------- - --spec out(integer(), pqueue2()) -> - {{'value', term()}, pqueue2()} | {'empty', pqueue2()}. - -out(_, empty) -> - {empty, empty}; -out(P, {P1, _, _, _, _} = H) when P < P1 -> - {empty, H}; -out(P, {P1, HL1, HR1, T, D}) when P > P1 -> - case out(P, HL1) of - {{value, _} = Result, HL2} -> - {Result, {P1, HL2, HR1, T, D}}; - {empty, HL2} -> - case out(P, HR1) of - {{value, _} = Result, HR2} -> - {Result, {P1, HL2, HR2, T, D}}; - {empty, HR2} -> - {empty, {P1, HL2, HR2, T, D}} - end - end; -out(P, {P, HL, HR, element, Value}) -> - {{value, Value}, merge(HL, HR)}; -out(P, {P, HL, HR, queue, Queue}) -> - case queue:out(Queue) of - {{value, _} = Result, NewQueue} -> - {Result, {P, HL, HR, queue, NewQueue}}; - {empty, _} -> - out(P, merge(HL, HR)) - end. - -%%------------------------------------------------------------------------- -%% @doc -%% ===Take an item from the head of the priority queue.=== -%% Includes the priority in the return value. -%% @end -%%------------------------------------------------------------------------- - --spec pout(pqueue2()) -> - {{'value', term(), integer()}, pqueue2()} | {'empty', pqueue2()}. - -pout(empty) -> - {empty, empty}; -pout({P, HL, HR, element, Value}) -> - {{value, Value, P}, merge(HL, HR)}; -pout({P, HL, HR, queue, Queue}) -> - case queue:out(Queue) of - {{value, Value}, NewQueue} -> - {{value, Value, P}, {P, HL, HR, queue, NewQueue}}; - {empty, _} -> - pout(merge(HL, HR)) - end. - -%%------------------------------------------------------------------------- -%% @doc -%% ===Convert the priority queue to a list.=== -%% @end -%%------------------------------------------------------------------------- - --spec to_list(pqueue2()) -> list(term()). - -to_list(H) -> - to_list([], out(H)). -to_list(L, {empty, _}) -> - lists:reverse(L); -to_list(L, {{value, Value}, H}) -> - to_list([Value | L], out(H)). - -%%------------------------------------------------------------------------- -%% @doc -%% ===Regression test.=== -%% @end -%%------------------------------------------------------------------------- - -test() -> - Q0 = pqueue2:new(), - true = pqueue2:is_queue(Q0), - Q1 = pqueue2:in(20, 20, Q0), - Q2 = pqueue2:in(19, 19, Q1), - Q3 = pqueue2:in(18, 18, Q2), - Q4 = pqueue2:in(17, 17, Q3), - Q5 = pqueue2:in(16, 16, Q4), - Q6 = pqueue2:in(15, 15, Q5), - Q7 = pqueue2:in(14, 14, Q6), - Q8 = pqueue2:in(13, 13, Q7), - Q9 = pqueue2:in(12, 12, Q8), - Q10 = pqueue2:in(11, 11, Q9), - Q11 = pqueue2:in(10, 10, Q10), - Q12 = pqueue2:in(9, 9, Q11), - Q13 = pqueue2:in(8, 8, Q12), - Q14 = pqueue2:in(7, 7, Q13), - Q15 = pqueue2:in(6, 6, Q14), - Q16 = pqueue2:in(5, 5, Q15), - Q17 = pqueue2:in(4, 4, Q16), - Q18 = pqueue2:in(3, 3, Q17), - Q19 = pqueue2:in(2, 2, Q18), - Q20 = pqueue2:in(1, 1, Q19), - Q21 = pqueue2:in(0, 0, Q20), - Q22 = pqueue2:in(-1, -1, Q21), - Q23 = pqueue2:in(-2, -2, Q22), - Q24 = pqueue2:in(-3, -3, Q23), - Q25 = pqueue2:in(-4, -4, Q24), - Q26 = pqueue2:in(-5, -5, Q25), - Q27 = pqueue2:in(-6, -6, Q26), - Q28 = pqueue2:in(-7, -7, Q27), - Q29 = pqueue2:in(-8, -8, Q28), - Q30 = pqueue2:in(-9, -9, Q29), - Q31 = pqueue2:in(-10, -10, Q30), - Q32 = pqueue2:in(-11, -11, Q31), - Q33 = pqueue2:in(-12, -12, Q32), - Q34 = pqueue2:in(-13, -13, Q33), - Q35 = pqueue2:in(-14, -14, Q34), - Q36 = pqueue2:in(-15, -15, Q35), - Q37 = pqueue2:in(-16, -16, Q36), - Q38 = pqueue2:in(-17, -17, Q37), - Q39 = pqueue2:in(-18, -18, Q38), - Q40 = pqueue2:in(-19, -19, Q39), - Q41 = pqueue2:in(-20, -20, Q40), - Q42 = pqueue2:in(-20, -20, Q41), - Q43 = pqueue2:in(-19, -19, Q42), - Q44 = pqueue2:in(-18, -18, Q43), - Q45 = pqueue2:in(-17, -17, Q44), - Q46 = pqueue2:in(-16, -16, Q45), - Q47 = pqueue2:in(-15, -15, Q46), - Q48 = pqueue2:in(-14, -14, Q47), - Q49 = pqueue2:in(-13, -13, Q48), - Q50 = pqueue2:in(-12, -12, Q49), - Q51 = pqueue2:in(-11, -11, Q50), - Q52 = pqueue2:in(-10, -10, Q51), - Q53 = pqueue2:in(-9, -9, Q52), - Q54 = pqueue2:in(-8, -8, Q53), - Q55 = pqueue2:in(-7, -7, Q54), - Q56 = pqueue2:in(-6, -6, Q55), - Q57 = pqueue2:in(-5, -5, Q56), - Q58 = pqueue2:in(-4, -4, Q57), - Q59 = pqueue2:in(-3, -3, Q58), - Q60 = pqueue2:in(-2, -2, Q59), - Q61 = pqueue2:in(-1, -1, Q60), - Q62 = pqueue2:in(0, 0, Q61), - Q63 = pqueue2:in(1, 1, Q62), - Q64 = pqueue2:in(2, 2, Q63), - Q65 = pqueue2:in(3, 3, Q64), - Q66 = pqueue2:in(4, 4, Q65), - Q67 = pqueue2:in(5, 5, Q66), - Q68 = pqueue2:in(6, 6, Q67), - Q69 = pqueue2:in(7, 7, Q68), - Q70 = pqueue2:in(8, 8, Q69), - Q71 = pqueue2:in(9, 9, Q70), - Q72 = pqueue2:in(10, 10, Q71), - Q73 = pqueue2:in(11, 11, Q72), - Q74 = pqueue2:in(12, 12, Q73), - Q75 = pqueue2:in(13, 13, Q74), - Q76 = pqueue2:in(14, 14, Q75), - Q77 = pqueue2:in(15, 15, Q76), - Q78 = pqueue2:in(16, 16, Q77), - Q79 = pqueue2:in(17, 17, Q78), - Q80 = pqueue2:in(18, 18, Q79), - Q81 = pqueue2:in(19, 19, Q80), - Q82 = pqueue2:in(20, 20, Q81), - true = pqueue2:is_queue(Q82), - 82 = pqueue2:len(Q82), - [-20, -20, -19, -19, -18, -18, -17, -17, -16, -16, -15, -15, -14, -14, - -13, -13, -12, -12, -11, -11, -10, -10, -9, -9, -8, -8, -7, -7, -6, -6, - -5, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, - 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, - 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20] = pqueue2:to_list(Q82), - {{value, -20}, Q83} = pqueue2:out(Q82), - {{value, -20}, Q84} = pqueue2:out(Q83), - {{value, -19}, Q85} = pqueue2:out(Q84), - {{value, -19}, Q86} = pqueue2:out(Q85), - {{value, -18}, Q87} = pqueue2:out(Q86), - {{value, -18}, Q88} = pqueue2:out(Q87), - {{value, 0}, Q89} = pqueue2:out(0, Q88), - {{value, 0}, Q90} = pqueue2:out(0, Q89), - {empty, _} = pqueue2:out(0, Q90), - {{value, -17, -17}, Q91} = pqueue2:pout(Q90), - {{value, -17, -17}, Q92} = pqueue2:pout(Q91), - {{value, -16, -16}, Q93} = pqueue2:pout(Q92), - {{value, -16, -16}, Q94} = pqueue2:pout(Q93), - {{value, -15, -15}, Q95} = pqueue2:pout(Q94), - {{value, -15, -15}, Q96} = pqueue2:pout(Q95), - {{value, -14, -14}, Q97} = pqueue2:pout(Q96), - {{value, -14, -14}, Q98} = pqueue2:pout(Q97), - {{value, -13, -13}, Q99} = pqueue2:pout(Q98), - {{value, -13, -13}, Q100} = pqueue2:pout(Q99), - {{value, -12, -12}, Q101} = pqueue2:pout(Q100), - {{value, -12, -12}, Q102} = pqueue2:pout(Q101), - {{value, -11, -11}, Q103} = pqueue2:pout(Q102), - {{value, -11, -11}, Q104} = pqueue2:pout(Q103), - {{value, -10, -10}, Q105} = pqueue2:pout(Q104), - {{value, -10, -10}, Q106} = pqueue2:pout(Q105), - {{value, -9, -9}, Q107} = pqueue2:pout(Q106), - {{value, -9, -9}, Q108} = pqueue2:pout(Q107), - {{value, -8, -8}, Q109} = pqueue2:pout(Q108), - {{value, -8, -8}, Q110} = pqueue2:pout(Q109), - {{value, -7, -7}, Q111} = pqueue2:pout(Q110), - {{value, -7, -7}, Q112} = pqueue2:pout(Q111), - {{value, -6, -6}, Q113} = pqueue2:pout(Q112), - {{value, -6, -6}, Q114} = pqueue2:pout(Q113), - {{value, -5, -5}, Q115} = pqueue2:pout(Q114), - {{value, -5, -5}, Q116} = pqueue2:pout(Q115), - {{value, -4, -4}, Q117} = pqueue2:pout(Q116), - {{value, -4, -4}, Q118} = pqueue2:pout(Q117), - {{value, -3, -3}, Q119} = pqueue2:pout(Q118), - {{value, -3, -3}, Q120} = pqueue2:pout(Q119), - {{value, -2, -2}, Q121} = pqueue2:pout(Q120), - {{value, -2, -2}, Q122} = pqueue2:pout(Q121), - {{value, -1, -1}, Q123} = pqueue2:pout(Q122), - {{value, -1, -1}, Q124} = pqueue2:pout(Q123), - {{value, 1, 1}, Q125} = pqueue2:pout(Q124), - {{value, 1, 1}, Q126} = pqueue2:pout(Q125), - {{value, 2, 2}, Q127} = pqueue2:pout(Q126), - {{value, 2, 2}, Q128} = pqueue2:pout(Q127), - {{value, 3, 3}, Q129} = pqueue2:pout(Q128), - {{value, 3, 3}, Q130} = pqueue2:pout(Q129), - {{value, 4, 4}, Q131} = pqueue2:pout(Q130), - {{value, 4, 4}, Q132} = pqueue2:pout(Q131), - {{value, 5, 5}, Q133} = pqueue2:pout(Q132), - {{value, 5, 5}, Q134} = pqueue2:pout(Q133), - {{value, 6, 6}, Q135} = pqueue2:pout(Q134), - {{value, 6, 6}, Q136} = pqueue2:pout(Q135), - {{value, 7, 7}, Q137} = pqueue2:pout(Q136), - {{value, 7, 7}, Q138} = pqueue2:pout(Q137), - {{value, 8, 8}, Q139} = pqueue2:pout(Q138), - {{value, 8, 8}, Q140} = pqueue2:pout(Q139), - {{value, 9, 9}, Q141} = pqueue2:pout(Q140), - {{value, 9, 9}, Q142} = pqueue2:pout(Q141), - {{value, 10, 10}, Q143} = pqueue2:pout(Q142), - {{value, 10, 10}, Q144} = pqueue2:pout(Q143), - {{value, 11, 11}, Q145} = pqueue2:pout(Q144), - {{value, 11, 11}, Q146} = pqueue2:pout(Q145), - {{value, 12, 12}, Q147} = pqueue2:pout(Q146), - {{value, 12, 12}, Q148} = pqueue2:pout(Q147), - {{value, 13, 13}, Q149} = pqueue2:pout(Q148), - {{value, 13, 13}, Q150} = pqueue2:pout(Q149), - {{value, 14, 14}, Q151} = pqueue2:pout(Q150), - {{value, 14, 14}, Q152} = pqueue2:pout(Q151), - {{value, 15, 15}, Q153} = pqueue2:pout(Q152), - {{value, 15, 15}, Q154} = pqueue2:pout(Q153), - {{value, 16, 16}, Q155} = pqueue2:pout(Q154), - {{value, 16, 16}, Q156} = pqueue2:pout(Q155), - {{value, 17, 17}, Q157} = pqueue2:pout(Q156), - {{value, 17, 17}, Q158} = pqueue2:pout(Q157), - {{value, 18, 18}, Q159} = pqueue2:pout(Q158), - {{value, 18, 18}, Q160} = pqueue2:pout(Q159), - {{value, 19, 19}, Q161} = pqueue2:pout(Q160), - {{value, 19, 19}, Q162} = pqueue2:pout(Q161), - {{value, 20, 20}, Q163} = pqueue2:pout(Q162), - {{value, 20, 20}, Q164} = pqueue2:pout(Q163), - true = pqueue2:is_empty(Q164), - {empty, Q165} = pqueue2:pout(Q164), - true = pqueue2:is_empty(Q165), - % test case 1, based on proper testing - C1V0 = pqueue2:in(-18, pqueue2:new()), - C1V1 = pqueue2:in(9, C1V0), - C1V2 = pqueue2:in(-10, -4, C1V1), - C1V3 = pqueue2:in(-29, C1V2), - C1V4 = pqueue2:in(11, C1V3), - 5 = pqueue2:len(C1V4), - [-10, -18, 9, -29, 11] = pqueue2:to_list(C1V4), - % test case 2, based on proper testing - C2V0 = pqueue2:in(-4, -15, pqueue2:new()), - C2V1 = pqueue2:in(13, C2V0), - C2V2 = pqueue2:in(2, C2V1), - [-4, 13, 2] = to_list(C2V2), - ok. - -%%%------------------------------------------------------------------------ -%%% Private functions -%%%------------------------------------------------------------------------ - -merge(empty, empty) -> - empty; -merge(empty, {_, _, _, _, _} = H) -> - H; -merge({_, _, _, _, _} = H, empty) -> - H; -merge({P1, HL1, HR1, T, D}, {P2, _, _, _, _} = H2) when P1 < P2 -> - {P1, HL1, merge(HR1, H2), T, D}; -merge({P1, _, _, _, _} = H1, {P2, HL2, HR2, T, D}) when P1 > P2 -> - {P2, HL2, merge(H1, HR2), T, D}; -merge({P, HL1, HR1, element, Value1}, {P, HL2, HR2, element, Value2}) -> - {P, merge(HL1, HR1), merge(HL2, HR2), queue, - queue:from_list([Value2, Value1])}; -merge({P, HL1, HR1, queue, Queue}, {P, HL2, HR2, element, Value}) -> - {P, merge(HL1, HR1), merge(HL2, HR2), queue, queue:in(Value, Queue)}; -merge({P, HL1, HR1, element, Value}, {P, HL2, HR2, queue, Queue}) -> - {P, merge(HL1, HR1), merge(HL2, HR2), queue, queue:in(Value, Queue)}. - --ifdef(TEST). --include_lib("eunit/include/eunit.hrl"). - --include("pqueue_test.hrl"). - -module_test_() -> - {timeout, ?TEST_TIMEOUT, [ - {"internal tests", ?_assertOk(test())} - ]}. - -long_test_() -> - test_condition([ - {"proper tests", ?_assert(pqueue_proper:qc_pq2())} - ], ?CLOUDI_LONG_TEST_TIMEOUT). - --endif. - |